1 Commits

Author SHA1 Message Date
tecnovert
a6e7d36e84 Add incoming mweb->plain amounts to unconfirmed balance 2024-02-09 23:49:57 +02:00
118 changed files with 10873 additions and 12341 deletions

1
.gitignore vendored
View File

@@ -12,4 +12,3 @@ __pycache__
# geckodriver.log # geckodriver.log
*.log *.log
docker/.env

View File

@@ -100,7 +100,7 @@ If youd like to add a cryptocurrency to BasicSwap, either [apply for a listin
### Chats ### Chats
* **For developers** The chat [#particl-dev:matrix.org](https://matrix.to/#/#particl-dev:matrix.org) using a Matrix client. * **For developers** The chat [#particl-dev:matrix.org](https://app.element.io/#/room/#particl-dev:matrix.org) using [Element](https://element.io) (formerly Riot).
* **For community** The community chat [https://discord.me/particl](https://discord.me/particl) [![Discord](https://img.shields.io/discord/391967609660112925)](https://discord.me/particl). * **For community** The community chat [https://discord.me/particl](https://discord.me/particl) [![Discord](https://img.shields.io/discord/391967609660112925)](https://discord.me/particl).
[![Twitter Follow](https://img.shields.io/twitter/follow/BasicSwapDEX?label=follow%20us&style=social)](http://twitter.com/BasicSwapDEX) [![Twitter Follow](https://img.shields.io/twitter/follow/BasicSwapDEX?label=follow%20us&style=social)](http://twitter.com/BasicSwapDEX)
@@ -118,7 +118,7 @@ For non-developers curious to explore a new world of commerce, binaries can be d
* [Telegram](https://t.me/particlhelp) * [Telegram](https://t.me/particlhelp)
* [Matrix](https://matrix.to/#/#particlhelp:matrix.org) * [Element](https://app.element.io/#/room/#particlhelp:matrix.org)
# Tutorials # Tutorials

View File

@@ -1,3 +1,3 @@
name = "basicswap" name = "basicswap"
__version__ = "0.13.1" __version__ = "0.12.7"

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2021-2024 tecnovert # Copyright (c) 2021-2023 tecnovert
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php. # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@@ -70,7 +70,6 @@ class OfferStates(IntEnum):
OFFER_SENT = 1 OFFER_SENT = 1
OFFER_RECEIVED = 2 OFFER_RECEIVED = 2
OFFER_ABANDONED = 3 OFFER_ABANDONED = 3
OFFER_EXPIRED = 4
class BidStates(IntEnum): class BidStates(IntEnum):
@@ -104,7 +103,6 @@ class BidStates(IntEnum):
XMR_SWAP_MSG_SCRIPT_LOCK_SPEND_TX = 28 # XmrBidLockSpendTxMessage XMR_SWAP_MSG_SCRIPT_LOCK_SPEND_TX = 28 # XmrBidLockSpendTxMessage
BID_REQUEST_SENT = 29 BID_REQUEST_SENT = 29
BID_REQUEST_ACCEPTED = 30 BID_REQUEST_ACCEPTED = 30
BID_EXPIRED = 31
class TxStates(IntEnum): class TxStates(IntEnum):
@@ -202,8 +200,6 @@ class DebugTypes(IntEnum):
SEND_LOCKED_XMR = auto() SEND_LOCKED_XMR = auto()
B_LOCK_TX_MISSED_SEND = auto() B_LOCK_TX_MISSED_SEND = auto()
DUPLICATE_ACTIONS = auto() DUPLICATE_ACTIONS = auto()
DONT_CONFIRM_PTX = auto()
OFFER_LOCK_2_VALUE_INC = auto()
class NotificationTypes(IntEnum): class NotificationTypes(IntEnum):
@@ -252,8 +248,6 @@ def strOfferState(state):
return 'Received' return 'Received'
if state == OfferStates.OFFER_ABANDONED: if state == OfferStates.OFFER_ABANDONED:
return 'Abandoned' return 'Abandoned'
if state == OfferStates.OFFER_EXPIRED:
return 'Expired'
return 'Unknown' return 'Unknown'
@@ -318,8 +312,7 @@ def strBidState(state):
return 'Request accepted' return 'Request accepted'
if state == BidStates.BID_STATE_UNKNOWN: if state == BidStates.BID_STATE_UNKNOWN:
return 'Unknown bid state' return 'Unknown bid state'
if state == BidStates.BID_EXPIRED:
return 'Expired'
return 'Unknown' + ' ' + str(state) return 'Unknown' + ' ' + str(state)
@@ -510,7 +503,7 @@ def strSwapDesc(swap_type):
return None return None
inactive_states = [BidStates.SWAP_COMPLETED, BidStates.BID_ERROR, BidStates.BID_REJECTED, BidStates.SWAP_TIMEDOUT, BidStates.BID_ABANDONED, BidStates.BID_EXPIRED] inactive_states = [BidStates.SWAP_COMPLETED, BidStates.BID_ERROR, BidStates.BID_REJECTED, BidStates.SWAP_TIMEDOUT, BidStates.BID_ABANDONED]
def isActiveBidState(state): def isActiveBidState(state):

View File

@@ -1,12 +1,17 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2019-2024 tecnovert # Copyright (c) 2019-2023 tecnovert
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php. # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
import threading
from enum import IntEnum from enum import IntEnum
from .util import ( from .util import (
COIN, COIN,
make_int,
format_amount,
TemporaryError,
) )
XMR_COIN = 10 ** 12 XMR_COIN = 10 ** 12
@@ -16,7 +21,7 @@ class Coins(IntEnum):
PART = 1 PART = 1
BTC = 2 BTC = 2
LTC = 3 LTC = 3
DCR = 4 # DCR = 4
NMC = 5 NMC = 5
XMR = 6 XMR = 6
PART_BLIND = 7 PART_BLIND = 7
@@ -150,41 +155,6 @@ chainparams = {
'max_amount': 100000 * COIN, 'max_amount': 100000 * COIN,
} }
}, },
Coins.DCR: {
'name': 'decred',
'ticker': 'DCR',
'message_magic': 'Decred Signed Message:\n',
'blocks_target': 60 * 5,
'decimal_places': 8,
'mainnet': {
'rpcport': 9109,
'pubkey_address': 0x073f,
'script_address': 0x071a,
'key_prefix': 0x22de,
'bip44': 42,
'min_amount': 1000,
'max_amount': 100000 * COIN,
},
'testnet': {
'rpcport': 19109,
'pubkey_address': 0x0f21,
'script_address': 0x0efc,
'key_prefix': 0x230e,
'bip44': 1,
'min_amount': 1000,
'max_amount': 100000 * COIN,
'name': 'testnet3',
},
'regtest': { # simnet
'rpcport': 18656,
'pubkey_address': 0x0e91,
'script_address': 0x0e6c,
'key_prefix': 0x2307,
'bip44': 1,
'min_amount': 1000,
'max_amount': 100000 * COIN,
}
},
Coins.NMC: { Coins.NMC: {
'name': 'namecoin', 'name': 'namecoin',
'ticker': 'NMC', 'ticker': 'NMC',
@@ -230,21 +200,18 @@ chainparams = {
'walletrpcport': 18082, 'walletrpcport': 18082,
'min_amount': 100000, 'min_amount': 100000,
'max_amount': 10000 * XMR_COIN, 'max_amount': 10000 * XMR_COIN,
'address_prefix': 18,
}, },
'testnet': { 'testnet': {
'rpcport': 28081, 'rpcport': 28081,
'walletrpcport': 28082, 'walletrpcport': 28082,
'min_amount': 100000, 'min_amount': 100000,
'max_amount': 10000 * XMR_COIN, 'max_amount': 10000 * XMR_COIN,
'address_prefix': 18,
}, },
'regtest': { 'regtest': {
'rpcport': 18081, 'rpcport': 18081,
'walletrpcport': 18082, 'walletrpcport': 18082,
'min_amount': 100000, 'min_amount': 100000,
'max_amount': 10000 * XMR_COIN, 'max_amount': 10000 * XMR_COIN,
'address_prefix': 18,
} }
}, },
Coins.PIVX: { Coins.PIVX: {
@@ -417,3 +384,89 @@ def getCoinIdFromTicker(ticker):
return ticker_map[ticker.lower()] return ticker_map[ticker.lower()]
except Exception: except Exception:
raise ValueError('Unknown coin') raise ValueError('Unknown coin')
class CoinInterface:
def __init__(self, network):
self.setDefaults()
self._network = network
self._mx_wallet = threading.Lock()
def setDefaults(self):
self._unknown_wallet_seed = True
self._restore_height = None
def make_int(self, amount_in: int, r: int = 0) -> int:
return make_int(amount_in, self.exp(), r=r)
def format_amount(self, amount_in, conv_int=False, r=0):
amount_int = make_int(amount_in, self.exp(), r=r) if conv_int else amount_in
return format_amount(amount_int, self.exp())
def coin_name(self) -> str:
coin_chainparams = chainparams[self.coin_type()]
if coin_chainparams.get('use_ticker_as_name', False):
return coin_chainparams['ticker']
return coin_chainparams['name'].capitalize()
def ticker(self) -> str:
ticker = chainparams[self.coin_type()]['ticker']
if self._network == 'testnet':
ticker = 't' + ticker
elif self._network == 'regtest':
ticker = 'rt' + ticker
return ticker
def getExchangeTicker(self, exchange_name: str) -> str:
return chainparams[self.coin_type()]['ticker']
def getExchangeName(self, exchange_name: str) -> str:
return chainparams[self.coin_type()]['name']
def ticker_mainnet(self) -> str:
ticker = chainparams[self.coin_type()]['ticker']
return ticker
def min_amount(self) -> int:
return chainparams[self.coin_type()][self._network]['min_amount']
def max_amount(self) -> int:
return chainparams[self.coin_type()][self._network]['max_amount']
def setWalletSeedWarning(self, value: bool) -> None:
self._unknown_wallet_seed = value
def setWalletRestoreHeight(self, value: int) -> None:
self._restore_height = value
def knownWalletSeed(self) -> bool:
return not self._unknown_wallet_seed
def chainparams(self):
return chainparams[self.coin_type()]
def chainparams_network(self):
return chainparams[self.coin_type()][self._network]
def has_segwit(self) -> bool:
return chainparams[self.coin_type()].get('has_segwit', True)
def is_transient_error(self, ex) -> bool:
if isinstance(ex, TemporaryError):
return True
str_error: str = str(ex).lower()
if 'not enough unlocked money' in str_error:
return True
if 'no unlocked balance' in str_error:
return True
if 'transaction was rejected by daemon' in str_error:
return True
if 'invalid unlocked_balance' in str_error:
return True
if 'daemon is busy' in str_error:
return True
if 'timed out' in str_error:
return True
if 'request-sent' in str_error:
return True
return False

View File

@@ -1 +0,0 @@

View File

@@ -1,533 +0,0 @@
intro = """
blake.py
version 5, 2-Apr-2014
BLAKE is a SHA3 round-3 finalist designed and submitted by
Jean-Philippe Aumasson et al.
At the core of BLAKE is a ChaCha-like mixer, very similar
to that found in the stream cipher, ChaCha8. Besides being
a very good mixer, ChaCha is fast.
References:
http://www.131002.net/blake/
http://csrc.nist.gov/groups/ST/hash/sha-3/index.html
http://en.wikipedia.org/wiki/BLAKE_(hash_function)
This implementation assumes all data is in increments of
whole bytes. (The formal definition of BLAKE allows for
hashing individual bits.) Note too that this implementation
does include the round-3 tweaks where the number of rounds
was increased to 14/16 from 10/14.
This version can be imported into both Python2 (2.6 and 2.7)
and Python3 programs. Python 2.5 requires an older version
of blake.py (version 4).
Here are some comparative times for different versions of
Python:
64-bit:
2.6 6.284s
2.7 6.343s
3.2 7.620s
pypy (2.7) 2.080s
32-bit:
2.5 (32) 15.389s (with psyco)
2.7-32 13.645s
3.2-32 12.574s
One test on a 2.0GHz Core 2 Duo of 10,000 iterations of
BLAKE-256 on a short message produced a time of 5.7 seconds.
Not bad, but if raw speed is what you want, look to the
the C version. It is 40x faster and did the same thing
in 0.13 seconds.
Copyright (c) 2009-2012 by Larry Bugbee, Kent, WA
ALL RIGHTS RESERVED.
blake.py IS EXPERIMENTAL SOFTWARE FOR EDUCATIONAL
PURPOSES ONLY. IT IS MADE AVAILABLE "AS-IS" WITHOUT
WARRANTY OR GUARANTEE OF ANY KIND. USE SIGNIFIES
ACCEPTANCE OF ALL RISK.
To make your learning and experimentation less cumbersome,
blake.py is free for any use.
Enjoy,
Larry Bugbee
March 2011
rev May 2011 - fixed Python version check (tx JP)
rev Apr 2012 - fixed an out-of-order bit set in final()
- moved self-test to a separate test pgm
- this now works with Python2 and Python3
rev Apr 2014 - added test and conversion of string input
to byte string in update() (tx Soham)
- added hexdigest() method.
- now support state 3 so only one call to
final() per instantiation is allowed. all
subsequent calls to final(), digest() or
hexdigest() simply return the stored value.
"""
import struct
from binascii import hexlify, unhexlify
#---------------------------------------------------------------
class BLAKE(object):
# - - - - - - - - - - - - - - - - - - - - - - - - - - -
# initial values, constants and padding
# IVx for BLAKE-x
IV64 = [
0x6A09E667F3BCC908, 0xBB67AE8584CAA73B,
0x3C6EF372FE94F82B, 0xA54FF53A5F1D36F1,
0x510E527FADE682D1, 0x9B05688C2B3E6C1F,
0x1F83D9ABFB41BD6B, 0x5BE0CD19137E2179,
]
IV48 = [
0xCBBB9D5DC1059ED8, 0x629A292A367CD507,
0x9159015A3070DD17, 0x152FECD8F70E5939,
0x67332667FFC00B31, 0x8EB44A8768581511,
0xDB0C2E0D64F98FA7, 0x47B5481DBEFA4FA4,
]
# note: the values here are the same as the high-order
# half-words of IV64
IV32 = [
0x6A09E667, 0xBB67AE85,
0x3C6EF372, 0xA54FF53A,
0x510E527F, 0x9B05688C,
0x1F83D9AB, 0x5BE0CD19,
]
# note: the values here are the same as the low-order
# half-words of IV48
IV28 = [
0xC1059ED8, 0x367CD507,
0x3070DD17, 0xF70E5939,
0xFFC00B31, 0x68581511,
0x64F98FA7, 0xBEFA4FA4,
]
# constants for BLAKE-64 and BLAKE-48
C64 = [
0x243F6A8885A308D3, 0x13198A2E03707344,
0xA4093822299F31D0, 0x082EFA98EC4E6C89,
0x452821E638D01377, 0xBE5466CF34E90C6C,
0xC0AC29B7C97C50DD, 0x3F84D5B5B5470917,
0x9216D5D98979FB1B, 0xD1310BA698DFB5AC,
0x2FFD72DBD01ADFB7, 0xB8E1AFED6A267E96,
0xBA7C9045F12C7F99, 0x24A19947B3916CF7,
0x0801F2E2858EFC16, 0x636920D871574E69,
]
# constants for BLAKE-32 and BLAKE-28
# note: concatenate and the values are the same as the values
# for the 1st half of C64
C32 = [
0x243F6A88, 0x85A308D3,
0x13198A2E, 0x03707344,
0xA4093822, 0x299F31D0,
0x082EFA98, 0xEC4E6C89,
0x452821E6, 0x38D01377,
0xBE5466CF, 0x34E90C6C,
0xC0AC29B7, 0xC97C50DD,
0x3F84D5B5, 0xB5470917,
]
# the 10 permutations of:0,...15}
SIGMA = [
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15],
[14,10, 4, 8, 9,15,13, 6, 1,12, 0, 2,11, 7, 5, 3],
[11, 8,12, 0, 5, 2,15,13,10,14, 3, 6, 7, 1, 9, 4],
[ 7, 9, 3, 1,13,12,11,14, 2, 6, 5,10, 4, 0,15, 8],
[ 9, 0, 5, 7, 2, 4,10,15,14, 1,11,12, 6, 8, 3,13],
[ 2,12, 6,10, 0,11, 8, 3, 4,13, 7, 5,15,14, 1, 9],
[12, 5, 1,15,14,13, 4,10, 0, 7, 6, 3, 9, 2, 8,11],
[13,11, 7,14,12, 1, 3, 9, 5, 0,15, 4, 8, 6, 2,10],
[ 6,15,14, 9,11, 3, 0, 8,12, 2,13, 7, 1, 4,10, 5],
[10, 2, 8, 4, 7, 6, 1, 5,15,11, 9,14, 3,12,13, 0],
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15],
[14,10, 4, 8, 9,15,13, 6, 1,12, 0, 2,11, 7, 5, 3],
[11, 8,12, 0, 5, 2,15,13,10,14, 3, 6, 7, 1, 9, 4],
[ 7, 9, 3, 1,13,12,11,14, 2, 6, 5,10, 4, 0,15, 8],
[ 9, 0, 5, 7, 2, 4,10,15,14, 1,11,12, 6, 8, 3,13],
[ 2,12, 6,10, 0,11, 8, 3, 4,13, 7, 5,15,14, 1, 9],
[12, 5, 1,15,14,13, 4,10, 0, 7, 6, 3, 9, 2, 8,11],
[13,11, 7,14,12, 1, 3, 9, 5, 0,15, 4, 8, 6, 2,10],
[ 6,15,14, 9,11, 3, 0, 8,12, 2,13, 7, 1, 4,10, 5],
[10, 2, 8, 4, 7, 6, 1, 5,15,11, 9,14, 3,12,13, 0],
]
MASK32BITS = 0xFFFFFFFF
MASK64BITS = 0xFFFFFFFFFFFFFFFF
# - - - - - - - - - - - - - - - - - - - - - - - - - - -
def __init__(self, hashbitlen):
"""
load the hashSate structure (copy hashbitlen...)
hashbitlen: length of the hash output
"""
if hashbitlen not in [224, 256, 384, 512]:
raise Exception('hash length not 224, 256, 384 or 512')
self.hashbitlen = hashbitlen
self.h = [0]*8 # current chain value (initialized to the IV)
self.t = 0 # number of *BITS* hashed so far
self.cache = b'' # cached leftover data not yet compressed
self.salt = [0]*4 # salt (null by default)
self.state = 1 # set to 2 by update and 3 by final
self.nullt = 0 # Boolean value for special case \ell_i=0
# The algorithm is the same for both the 32- and 64- versions
# of BLAKE. The difference is in word size (4 vs 8 bytes),
# blocksize (64 vs 128 bytes), number of rounds (14 vs 16)
# and a few very specific constants.
if (hashbitlen == 224) or (hashbitlen == 256):
# setup for 32-bit words and 64-bit block
self.byte2int = self._fourByte2int
self.int2byte = self._int2fourByte
self.MASK = self.MASK32BITS
self.WORDBYTES = 4
self.WORDBITS = 32
self.BLKBYTES = 64
self.BLKBITS = 512
self.ROUNDS = 14 # was 10 before round 3
self.cxx = self.C32
self.rot1 = 16 # num bits to shift in G
self.rot2 = 12 # num bits to shift in G
self.rot3 = 8 # num bits to shift in G
self.rot4 = 7 # num bits to shift in G
self.mul = 0 # for 32-bit words, 32<<self.mul where self.mul = 0
# 224- and 256-bit versions (32-bit words)
if hashbitlen == 224:
self.h = self.IV28[:]
else:
self.h = self.IV32[:]
elif (hashbitlen == 384) or (hashbitlen == 512):
# setup for 64-bit words and 128-bit block
self.byte2int = self._eightByte2int
self.int2byte = self._int2eightByte
self.MASK = self.MASK64BITS
self.WORDBYTES = 8
self.WORDBITS = 64
self.BLKBYTES = 128
self.BLKBITS = 1024
self.ROUNDS = 16 # was 14 before round 3
self.cxx = self.C64
self.rot1 = 32 # num bits to shift in G
self.rot2 = 25 # num bits to shift in G
self.rot3 = 16 # num bits to shift in G
self.rot4 = 11 # num bits to shift in G
self.mul = 1 # for 64-bit words, 32<<self.mul where self.mul = 1
# 384- and 512-bit versions (64-bit words)
if hashbitlen == 384:
self.h = self.IV48[:]
else:
self.h = self.IV64[:]
# - - - - - - - - - - - - - - - - - - - - - - - - - - -
def _compress(self, block):
byte2int = self.byte2int
mul = self.mul # de-reference these for ...speed? ;-)
cxx = self.cxx
rot1 = self.rot1
rot2 = self.rot2
rot3 = self.rot3
rot4 = self.rot4
MASK = self.MASK
WORDBITS = self.WORDBITS
SIGMA = self.SIGMA
# get message (<<2 is the same as *4 but faster)
m = [byte2int(block[i<<2<<mul:(i<<2<<mul)+(4<<mul)]) for i in range(16)]
# initialization
v = [0]*16
v[ 0: 8] = [self.h[i] for i in range(8)]
v[ 8:16] = [self.cxx[i] for i in range(8)]
v[ 8:12] = [v[8+i] ^ self.salt[i] for i in range(4)]
if self.nullt == 0: # (i>>1 is the same as i/2 but faster)
v[12] = v[12] ^ (self.t & MASK)
v[13] = v[13] ^ (self.t & MASK)
v[14] = v[14] ^ (self.t >> self.WORDBITS)
v[15] = v[15] ^ (self.t >> self.WORDBITS)
# - - - - - - - - - - - - - - - - -
# ready? let's ChaCha!!!
def G(a, b, c, d, i):
va = v[a] # it's faster to deref and reref later
vb = v[b]
vc = v[c]
vd = v[d]
sri = SIGMA[round][i]
sri1 = SIGMA[round][i+1]
va = ((va + vb) + (m[sri] ^ cxx[sri1]) ) & MASK
x = vd ^ va
vd = (x >> rot1) | ((x << (WORDBITS-rot1)) & MASK)
vc = (vc + vd) & MASK
x = vb ^ vc
vb = (x >> rot2) | ((x << (WORDBITS-rot2)) & MASK)
va = ((va + vb) + (m[sri1] ^ cxx[sri]) ) & MASK
x = vd ^ va
vd = (x >> rot3) | ((x << (WORDBITS-rot3)) & MASK)
vc = (vc + vd) & MASK
x = vb ^ vc
vb = (x >> rot4) | ((x << (WORDBITS-rot4)) & MASK)
v[a] = va
v[b] = vb
v[c] = vc
v[d] = vd
for round in range(self.ROUNDS):
# column step
G( 0, 4, 8,12, 0)
G( 1, 5, 9,13, 2)
G( 2, 6,10,14, 4)
G( 3, 7,11,15, 6)
# diagonal step
G( 0, 5,10,15, 8)
G( 1, 6,11,12,10)
G( 2, 7, 8,13,12)
G( 3, 4, 9,14,14)
# - - - - - - - - - - - - - - - - -
# save current hash value (use i&0x3 to get 0,1,2,3,0,1,2,3)
self.h = [self.h[i]^v[i]^v[i+8]^self.salt[i&0x3]
for i in range(8)]
# print 'self.h', [num2hex(h) for h in self.h]
# - - - - - - - - - - - - - - - - - - - - - - - - - - -
def addsalt(self, salt):
""" adds a salt to the hash function (OPTIONAL)
should be called AFTER Init, and BEFORE update
salt: a bytestring, length determined by hashbitlen.
if not of sufficient length, the bytestring
will be assumed to be a big endian number and
prefixed with an appropriate number of null
bytes, and if too large, only the low order
bytes will be used.
if hashbitlen=224 or 256, then salt will be 16 bytes
if hashbitlen=384 or 512, then salt will be 32 bytes
"""
# fail if addsalt() was not called at the right time
if self.state != 1:
raise Exception('addsalt() not called after init() and before update()')
# salt size is to be 4x word size
saltsize = self.WORDBYTES * 4
# if too short, prefix with null bytes. if too long,
# truncate high order bytes
if len(salt) < saltsize:
salt = (chr(0)*(saltsize-len(salt)) + salt)
else:
salt = salt[-saltsize:]
# prep the salt array
self.salt[0] = self.byte2int(salt[ : 4<<self.mul])
self.salt[1] = self.byte2int(salt[ 4<<self.mul: 8<<self.mul])
self.salt[2] = self.byte2int(salt[ 8<<self.mul:12<<self.mul])
self.salt[3] = self.byte2int(salt[12<<self.mul: ])
# - - - - - - - - - - - - - - - - - - - - - - - - - - -
def update(self, data):
""" update the state with new data, storing excess data
as necessary. may be called multiple times and if a
call sends less than a full block in size, the leftover
is cached and will be consumed in the next call
data: data to be hashed (bytestring)
"""
self.state = 2
BLKBYTES = self.BLKBYTES # de-referenced for improved readability
BLKBITS = self.BLKBITS
datalen = len(data)
if not datalen: return
if type(data) == type(u''):
# use either of the next two lines for a proper
# response under both Python2 and Python3
data = data.encode('UTF-8') # converts to byte string
#data = bytearray(data, 'utf-8') # use if want mutable
# This next line works for Py3 but fails under
# Py2 because the Py2 version of bytes() will
# accept only *one* argument. Arrrrgh!!!
#data = bytes(data, 'utf-8') # converts to immutable byte
# string but... under p7
# bytes() wants only 1 arg
# ...a dummy, 2nd argument like encoding=None
# that does nothing would at least allow
# compatibility between Python2 and Python3.
left = len(self.cache)
fill = BLKBYTES - left
# if any cached data and any added new data will fill a
# full block, fill and compress
if left and datalen >= fill:
self.cache = self.cache + data[:fill]
self.t += BLKBITS # update counter
self._compress(self.cache)
self.cache = b''
data = data[fill:]
datalen -= fill
# compress new data until not enough for a full block
while datalen >= BLKBYTES:
self.t += BLKBITS # update counter
self._compress(data[:BLKBYTES])
data = data[BLKBYTES:]
datalen -= BLKBYTES
# cache all leftover bytes until next call to update()
if datalen > 0:
self.cache = self.cache + data[:datalen]
# - - - - - - - - - - - - - - - - - - - - - - - - - - -
def final(self, data=''):
""" finalize the hash -- pad and hash remaining data
returns hashval, the digest
"""
if self.state == 3:
# we have already finalized so simply return the
# previously calculated/stored hash value
return self.hash
if data:
self.update(data)
ZZ = b'\x00'
ZO = b'\x01'
OZ = b'\x80'
OO = b'\x81'
PADDING = OZ + ZZ*128 # pre-formatted padding data
# copy nb. bits hash in total as a 64-bit BE word
# copy nb. bits hash in total as a 128-bit BE word
tt = self.t + (len(self.cache) << 3)
if self.BLKBYTES == 64:
msglen = self._int2eightByte(tt)
else:
low = tt & self.MASK
high = tt >> self.WORDBITS
msglen = self._int2eightByte(high) + self._int2eightByte(low)
# size of block without the words at the end that count
# the number of bits, 55 or 111.
# Note: (((self.WORDBITS/8)*2)+1) equals ((self.WORDBITS>>2)+1)
sizewithout = self.BLKBYTES - ((self.WORDBITS>>2)+1)
if len(self.cache) == sizewithout:
# special case of one padding byte
self.t -= 8
if self.hashbitlen in [224, 384]:
self.update(OZ)
else:
self.update(OO)
else:
if len(self.cache) < sizewithout:
# enough space to fill the block
# use t=0 if no remaining data
if len(self.cache) == 0:
self.nullt=1
self.t -= (sizewithout - len(self.cache)) << 3
self.update(PADDING[:sizewithout - len(self.cache)])
else:
# NOT enough space, need 2 compressions
# ...add marker, pad with nulls and compress
self.t -= (self.BLKBYTES - len(self.cache)) << 3
self.update(PADDING[:self.BLKBYTES - len(self.cache)])
# ...now pad w/nulls leaving space for marker & bit count
self.t -= (sizewithout+1) << 3
self.update(PADDING[1:sizewithout+1]) # pad with zeroes
self.nullt = 1 # raise flag to set t=0 at the next _compress
# append a marker byte
if self.hashbitlen in [224, 384]:
self.update(ZZ)
else:
self.update(ZO)
self.t -= 8
# append the number of bits (long long)
self.t -= self.BLKBYTES
self.update(msglen)
hashval = []
if self.BLKBYTES == 64:
for h in self.h:
hashval.append(self._int2fourByte(h))
else:
for h in self.h:
hashval.append(self._int2eightByte(h))
self.hash = b''.join(hashval)[:self.hashbitlen >> 3]
self.state = 3
return self.hash
digest = final # may use digest() as a synonym for final()
# - - - - - - - - - - - - - - - - - - - - - - - - - - -
def hexdigest(self, data=''):
return hexlify(self.final(data)).decode('UTF-8')
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# utility functions
def _fourByte2int(self, bytestr): # see also long2byt() below
""" convert a 4-byte string to an int (long) """
return struct.unpack('!L', bytestr)[0]
def _eightByte2int(self, bytestr):
""" convert a 8-byte string to an int (long long) """
return struct.unpack('!Q', bytestr)[0]
def _int2fourByte(self, x): # see also long2byt() below
""" convert a number to a 4-byte string, high order
truncation possible (in Python x could be a BIGNUM)
"""
return struct.pack('!L', x)
def _int2eightByte(self, x):
""" convert a number to a 8-byte string, high order
truncation possible (in Python x could be a BIGNUM)
"""
return struct.pack('!Q', x)
#---------------------------------------------------------------
#---------------------------------------------------------------
#---------------------------------------------------------------
def blake_hash(data):
return BLAKE(256).digest(data)

View File

@@ -1,37 +0,0 @@
from blake256 import blake_hash
testVectors = [
["716f6e863f744b9ac22c97ec7b76ea5f5908bc5b2f67c61510bfc4751384ea7a", ""],
["43234ff894a9c0590d0246cfc574eb781a80958b01d7a2fa1ac73c673ba5e311", "a"],
["658c6d9019a1deddbcb3640a066dfd23471553a307ab941fd3e677ba887be329", "ab"],
["1833a9fa7cf4086bd5fda73da32e5a1d75b4c3f89d5c436369f9d78bb2da5c28", "abc"],
["35282468f3b93c5aaca6408582fced36e578f67671ed0741c332d68ac72d7aa2", "abcd"],
["9278d633efce801c6aa62987d7483d50e3c918caed7d46679551eed91fba8904", "abcde"],
["7a17ee5e289845adcafaf6ca1b05c4a281b232a71c7083f66c19ba1d1169a8d4", "abcdef"],
["ee8c7f94ff805cb2e644643010ea43b0222056420917ec70c3da764175193f8f", "abcdefg"],
["7b37c0876d29c5add7800a1823795a82b809fc12f799ff6a4b5e58d52c42b17e", "abcdefgh"],
["bdc514bea74ffbb9c3aa6470b08ceb80a88e313ad65e4a01457bbffd0acc86de", "abcdefghi"],
["12e3afb9739df8d727e93d853faeafc374cc55aedc937e5a1e66f5843b1d4c2e", "abcdefghij"],
["22297d373b751f581944bb26315133f6fda2f0bf60f65db773900f61f81b7e79", "Discard medicine more than two years old."],
["4d48d137bc9cf6d21415b805bf33f59320337d85c673998260e03a02a0d760cd", "He who has a shady past knows that nice guys finish last."],
["beba299e10f93e17d45663a6dc4b8c9349e4f5b9bac0d7832389c40a1b401e5c", "I wouldn't marry him with a ten foot pole."],
["42e082ae7f967781c6cd4e0ceeaeeb19fb2955adbdbaf8c7ec4613ac130071b3", "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave"],
["207d06b205bfb359df91b48b6fd8aa6e4798b712d1cc5e91a254da9cef8684a3", "The days of the digital watch are numbered. -Tom Stoppard"],
["d56eab6927e371e2148b0788779aaf565d30567af2af822b6be3b90db9767a70", "Nepal premier won't resign."],
["01020709ca7fd10dc7756ce767d508d7206167d300b7a7ed76838a8547a7898c", "For every action there is an equal and opposite government program."],
["5569a6cc6535a66da221d8f6ad25008f28752d0343f3f1d757f1ecc9b1c61536", "His money is twice tainted: 'taint yours and 'taint mine."],
["8ff699b5ac7687c82600e89d0ff6cfa87e7179759184386971feb76fbae9975f", "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977"],
["f4b3a7c85a418b15ce330fd41ae0254b036ad48dd98aa37f0506a995ba9c6029", "It's a tiny change to the code and not completely disgusting. - Bob Manchek"],
["1ed94bab64fe560ef0983165fcb067e9a8a971c1db8e6fb151ff9a7c7fe877e3", "size: a.out: bad magic"],
["ff15b54992eedf9889f7b4bbb16692881aa01ed10dfc860fdb04785d8185cd3c", "The major problem is with sendmail. -Mark Horton"],
["8a0a7c417a47deec0b6474d8c247da142d2e315113a2817af3de8f45690d8652", "Give me a rock, paper and scissors and I will move the world. CCFestoon"],
["310d263fdab056a930324cdea5f46f9ea70219c1a74b01009994484113222a62", "If the enemy is within range, then so are you."],
["1aaa0903aa4cf872fe494c322a6e535698ea2140e15f26fb6088287aedceb6ba", "It's well we cannot hear the screams/That we create in others' dreams."],
["2eb81bcaa9e9185a7587a1b26299dcfb30f2a58a7f29adb584b969725457ad4f", "You remind me of a TV show, but that's all right: I watch it anyway."],
["c27b1683ef76e274680ab5492e592997b0d9d5ac5a5f4651b6036f64215256af", "C is as portable as Stonehedge!!"],
["3995cce8f32b174c22ffac916124bd095c80205d9d5f1bb08a155ac24b40d6cb", "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley"],
["496f7063f8bd479bf54e9d87e9ba53e277839ac7fdaecc5105f2879b58ee562f", "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule"],
["2e0eff918940b01eea9539a02212f33ee84f77fab201f4287aa6167e4a1ed043", "How can you write a big system without C++? -Paul Glick"]]
for vectorSet in testVectors:
assert vectorSet[0] == blake_hash(vectorSet[1]).encode('hex')

View File

@@ -1,17 +1,18 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2019-2024 tecnovert # Copyright (c) 2019-2023 tecnovert
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php. # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
import time import time
import struct
import sqlalchemy as sa import sqlalchemy as sa
from enum import IntEnum, auto from enum import IntEnum, auto
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.declarative import declarative_base
CURRENT_DB_VERSION = 24 CURRENT_DB_VERSION = 22
CURRENT_DB_DATA_VERSION = 4 CURRENT_DB_DATA_VERSION = 4
Base = declarative_base() Base = declarative_base()
@@ -33,10 +34,6 @@ def strConcepts(state):
return 'Unknown' return 'Unknown'
def pack_state(new_state: int, now: int) -> bytes:
return int(new_state).to_bytes(4, 'little') + now.to_bytes(8, 'little')
class DBKVInt(Base): class DBKVInt(Base):
__tablename__ = 'kv_int' __tablename__ = 'kv_int'
@@ -61,7 +58,6 @@ class Offer(Base):
coin_from = sa.Column(sa.Integer) coin_from = sa.Column(sa.Integer)
coin_to = sa.Column(sa.Integer) coin_to = sa.Column(sa.Integer)
amount_from = sa.Column(sa.BigInteger) amount_from = sa.Column(sa.BigInteger)
amount_to = sa.Column(sa.BigInteger)
rate = sa.Column(sa.BigInteger) rate = sa.Column(sa.BigInteger)
min_bid_amount = sa.Column(sa.BigInteger) min_bid_amount = sa.Column(sa.BigInteger)
time_valid = sa.Column(sa.BigInteger) time_valid = sa.Column(sa.BigInteger)
@@ -100,9 +96,9 @@ class Offer(Base):
now = int(time.time()) now = int(time.time())
self.state = new_state self.state = new_state
if self.states is None: if self.states is None:
self.states = pack_state(new_state, now) self.states = struct.pack('<iq', new_state, now)
else: else:
self.states += pack_state(new_state, now) self.states += struct.pack('<iq', new_state, now)
class Bid(Base): class Bid(Base):
@@ -127,7 +123,6 @@ class Bid(Base):
amount_to = sa.Column(sa.BigInteger) # amount * offer.rate amount_to = sa.Column(sa.BigInteger) # amount * offer.rate
pkhash_buyer = sa.Column(sa.LargeBinary) pkhash_buyer = sa.Column(sa.LargeBinary)
pkhash_buyer_to = sa.Column(sa.LargeBinary) # Used for the ptx if coin pubkey hashes differ
amount = sa.Column(sa.BigInteger) amount = sa.Column(sa.BigInteger)
rate = sa.Column(sa.BigInteger) rate = sa.Column(sa.BigInteger)
@@ -188,14 +183,9 @@ class Bid(Base):
if state_note is not None: if state_note is not None:
self.state_note = state_note self.state_note = state_note
if self.states is None: if self.states is None:
self.states = pack_state(new_state, now) self.states = struct.pack('<iq', new_state, now)
else: else:
self.states += pack_state(new_state, now) self.states += struct.pack('<iq', new_state, now)
def getLockTXBVout(self):
if self.xmr_b_lock_tx:
return self.xmr_b_lock_tx.vout
return None
class SwapTx(Base): class SwapTx(Base):
@@ -232,11 +222,7 @@ class SwapTx(Base):
if self.state == new_state: if self.state == new_state:
return return
self.state = new_state self.state = new_state
now: int = int(time.time()) self.states = (self.states if self.states is not None else bytes()) + struct.pack('<iq', new_state, int(time.time()))
if self.states is None:
self.states = pack_state(new_state, now)
else:
self.states += pack_state(new_state, now)
class PrefundedTx(Base): class PrefundedTx(Base):
@@ -528,14 +514,3 @@ class MessageLink(Base):
msg_type = sa.Column(sa.Integer) msg_type = sa.Column(sa.Integer)
msg_sequence = sa.Column(sa.Integer) msg_sequence = sa.Column(sa.Integer)
msg_id = sa.Column(sa.LargeBinary) msg_id = sa.Column(sa.LargeBinary)
class CheckedBlock(Base):
__tablename__ = 'checkedblocks'
record_id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)
created_at = sa.Column(sa.BigInteger)
coin_type = sa.Column(sa.Integer)
block_height = sa.Column(sa.Integer)
block_hash = sa.Column(sa.LargeBinary)
block_time = sa.Column(sa.BigInteger)

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2022-2024 tecnovert # Copyright (c) 2022-2023 tecnovert
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php. # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@@ -297,21 +297,7 @@ def upgradeDatabase(self, db_version):
db_version += 1 db_version += 1
session.execute('ALTER TABLE offers ADD COLUMN proof_utxos BLOB') session.execute('ALTER TABLE offers ADD COLUMN proof_utxos BLOB')
session.execute('ALTER TABLE bids ADD COLUMN proof_utxos BLOB') session.execute('ALTER TABLE bids ADD COLUMN proof_utxos BLOB')
elif current_version == 22:
db_version += 1
session.execute('ALTER TABLE offers ADD COLUMN amount_to INTEGER')
elif current_version == 23:
db_version += 1
session.execute('''
CREATE TABLE checkedblocks (
record_id INTEGER NOT NULL,
created_at BIGINT,
coin_type INTEGER,
block_height INTEGER,
block_hash BLOB,
block_time INTEGER,
PRIMARY KEY (record_id))''')
session.execute('ALTER TABLE bids ADD COLUMN pkhash_buyer_to BLOB')
if current_version != db_version: if current_version != db_version:
self.db_version = db_version self.db_version = db_version
self.setIntKVInSession('db_version', db_version, session) self.setIntKVInSession('db_version', db_version, session)

View File

@@ -52,7 +52,5 @@ def remove_expired_data(self, time_offset: int = 0):
if num_offers > 0 or num_bids > 0: if num_offers > 0 or num_bids > 0:
self.log.info('Removed data for {} expired offer{} and {} bid{}.'.format(num_offers, 's' if num_offers != 1 else '', num_bids, 's' if num_bids != 1 else '')) self.log.info('Removed data for {} expired offer{} and {} bid{}.'.format(num_offers, 's' if num_offers != 1 else '', num_bids, 's' if num_bids != 1 else ''))
session.execute('DELETE FROM checkedblocks WHERE created_at <= :expired_at', {'expired_at': now - time_offset})
finally: finally:
self.closeSession(session) self.closeSession(session)

View File

@@ -98,8 +98,6 @@ def parse_cmd(cmd: str, type_map: str):
type_ind = type_map[i] type_ind = type_map[i]
if type_ind == 'i': if type_ind == 'i':
typed_params.append(int(param)) typed_params.append(int(param))
elif type_ind == 'f':
typed_params.append(float(param))
elif type_ind == 'b': elif type_ind == 'b':
typed_params.append(toBool(param)) typed_params.append(toBool(param))
elif type_ind == 'j': elif type_ind == 'j':
@@ -267,7 +265,6 @@ class HttpHandler(BaseHTTPRequestHandler):
summary = swap_client.getSummary() summary = swap_client.getSummary()
result = None result = None
cmd = ''
coin_type = -1 coin_type = -1
coin_id = -1 coin_id = -1
call_type = 'cli' call_type = 'cli'
@@ -285,16 +282,11 @@ class HttpHandler(BaseHTTPRequestHandler):
coin_type = Coins(Coins.XMR) coin_type = Coins(Coins.XMR)
elif coin_id in (-5,): elif coin_id in (-5,):
coin_type = Coins(Coins.LTC) coin_type = Coins(Coins.LTC)
elif coin_id in (-6,):
coin_type = Coins(Coins.DCR)
else: else:
coin_type = Coins(coin_id) coin_type = Coins(coin_id)
except Exception: except Exception:
raise ValueError('Unknown Coin Type') raise ValueError('Unknown Coin Type')
if coin_type in (Coins.DCR,):
call_type = 'http'
try: try:
cmd = get_data_entry(form_data, 'cmd') cmd = get_data_entry(form_data, 'cmd')
except Exception: except Exception:
@@ -317,24 +309,18 @@ class HttpHandler(BaseHTTPRequestHandler):
result = json.dumps(rv, indent=4) result = json.dumps(rv, indent=4)
else: else:
if call_type == 'http': if call_type == 'http':
ci = swap_client.ci(coin_type)
method, params = parse_cmd(cmd, type_map) method, params = parse_cmd(cmd, type_map)
if coin_id == -6: if coin_id == -5:
rv = ci.rpc_wallet(method, params) rv = swap_client.ci(coin_type).rpc_wallet_mweb(method, params)
elif coin_id == -5:
rv = ci.rpc_wallet_mweb(method, params)
else: else:
if coin_type in (Coins.DCR, ): rv = swap_client.ci(coin_type).rpc_wallet(method, params)
rv = ci.rpc(method, params)
else:
rv = ci.rpc_wallet(method, params)
if not isinstance(rv, str): if not isinstance(rv, str):
rv = json.dumps(rv, indent=4) rv = json.dumps(rv, indent=4)
result = cmd + '\n' + rv result = cmd + '\n' + rv
else: else:
result = cmd + '\n' + swap_client.callcoincli(coin_type, cmd) result = cmd + '\n' + swap_client.callcoincli(coin_type, cmd)
except Exception as ex: except Exception as ex:
result = cmd + '\n' + str(ex) result = str(ex)
if self.server.swap_client.debug is True: if self.server.swap_client.debug is True:
self.server.swap_client.log.error(traceback.format_exc()) self.server.swap_client.log.error(traceback.format_exc())
@@ -344,8 +330,6 @@ class HttpHandler(BaseHTTPRequestHandler):
with_xmr: bool = any(c[0] == Coins.XMR for c in coins) with_xmr: bool = any(c[0] == Coins.XMR for c in coins)
coins = [c for c in coins if c[0] != Coins.XMR] coins = [c for c in coins if c[0] != Coins.XMR]
if any(c[0] == Coins.DCR for c in coins):
coins.append((-6, 'Decred Wallet'))
if any(c[0] == Coins.LTC for c in coins): if any(c[0] == Coins.LTC for c in coins):
coins.append((-5, 'Litecoin MWEB Wallet')) coins.append((-5, 'Litecoin MWEB Wallet'))
if with_xmr: if with_xmr:

View File

@@ -0,0 +1,13 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2023 tecnovert
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
from enum import IntEnum
class Curves(IntEnum):
secp256k1 = 1
ed25519 = 2

View File

@@ -1,238 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2024 tecnovert
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
import threading
from enum import IntEnum
from basicswap.chainparams import (
chainparams,
)
from basicswap.util import (
ensure,
i2b, b2i,
make_int,
format_amount,
TemporaryError,
)
from basicswap.util.crypto import (
hash160,
)
from basicswap.util.ecc import (
ep,
getSecretInt,
)
from coincurve.dleag import (
verify_secp256k1_point
)
from coincurve.keys import (
PublicKey,
)
class Curves(IntEnum):
secp256k1 = 1
ed25519 = 2
class CoinInterface:
@staticmethod
def watch_blocks_for_scripts() -> bool:
return False
@staticmethod
def compareFeeRates(a, b) -> bool:
return abs(a - b) < 20
def __init__(self, network):
self.setDefaults()
self._network = network
self._mx_wallet = threading.Lock()
def setDefaults(self):
self._unknown_wallet_seed = True
self._restore_height = None
def make_int(self, amount_in: int, r: int = 0) -> int:
return make_int(amount_in, self.exp(), r=r)
def format_amount(self, amount_in, conv_int=False, r=0):
amount_int = make_int(amount_in, self.exp(), r=r) if conv_int else amount_in
return format_amount(amount_int, self.exp())
def coin_name(self) -> str:
coin_chainparams = chainparams[self.coin_type()]
if coin_chainparams.get('use_ticker_as_name', False):
return coin_chainparams['ticker']
return coin_chainparams['name'].capitalize()
def ticker(self) -> str:
ticker = chainparams[self.coin_type()]['ticker']
if self._network == 'testnet':
ticker = 't' + ticker
elif self._network == 'regtest':
ticker = 'rt' + ticker
return ticker
def getExchangeTicker(self, exchange_name: str) -> str:
return chainparams[self.coin_type()]['ticker']
def getExchangeName(self, exchange_name: str) -> str:
return chainparams[self.coin_type()]['name']
def ticker_mainnet(self) -> str:
ticker = chainparams[self.coin_type()]['ticker']
return ticker
def min_amount(self) -> int:
return chainparams[self.coin_type()][self._network]['min_amount']
def max_amount(self) -> int:
return chainparams[self.coin_type()][self._network]['max_amount']
def setWalletSeedWarning(self, value: bool) -> None:
self._unknown_wallet_seed = value
def setWalletRestoreHeight(self, value: int) -> None:
self._restore_height = value
def knownWalletSeed(self) -> bool:
return not self._unknown_wallet_seed
def chainparams(self):
return chainparams[self.coin_type()]
def chainparams_network(self):
return chainparams[self.coin_type()][self._network]
def has_segwit(self) -> bool:
return chainparams[self.coin_type()].get('has_segwit', True)
def use_p2shp2wsh(self) -> bool:
# p2sh-p2wsh
return False
def is_transient_error(self, ex) -> bool:
if isinstance(ex, TemporaryError):
return True
str_error: str = str(ex).lower()
if 'not enough unlocked money' in str_error:
return True
if 'no unlocked balance' in str_error:
return True
if 'transaction was rejected by daemon' in str_error:
return True
if 'invalid unlocked_balance' in str_error:
return True
if 'daemon is busy' in str_error:
return True
if 'timed out' in str_error:
return True
if 'request-sent' in str_error:
return True
return False
def setConfTarget(self, new_conf_target: int) -> None:
ensure(new_conf_target >= 1 and new_conf_target < 33, 'Invalid conf_target value')
self._conf_target = new_conf_target
def walletRestoreHeight(self) -> int:
return self._restore_height
def get_connection_type(self):
return self._connection_type
def using_segwit(self) -> bool:
# Using btc native segwit
return self._use_segwit
def use_tx_vsize(self) -> bool:
return self._use_segwit
def getLockTxSwapOutputValue(self, bid, xmr_swap) -> int:
return bid.amount
def getLockRefundTxSwapOutputValue(self, bid, xmr_swap) -> int:
return xmr_swap.a_swap_refund_value
def getLockRefundTxSwapOutput(self, xmr_swap) -> int:
# Only one prevout exists
return 0
def checkWallets(self) -> int:
return 1
class AdaptorSigInterface():
def getScriptLockTxDummyWitness(self, script: bytes):
return [
b'',
bytes(72),
bytes(72),
bytes(len(script))
]
def getScriptLockRefundSpendTxDummyWitness(self, script: bytes):
return [
b'',
bytes(72),
bytes(72),
bytes((1,)),
bytes(len(script))
]
def getScriptLockRefundSwipeTxDummyWitness(self, script: bytes):
return [
bytes(72),
b'',
bytes(len(script))
]
class Secp256k1Interface(CoinInterface, AdaptorSigInterface):
@staticmethod
def curve_type():
return Curves.secp256k1
def getNewSecretKey(self) -> bytes:
return i2b(getSecretInt())
def getPubkey(self, privkey: bytes) -> bytes:
return PublicKey.from_secret(privkey).format()
def pkh(self, pubkey: bytes) -> bytes:
return hash160(pubkey)
def verifyKey(self, k: bytes) -> bool:
i = b2i(k)
return (i < ep.o and i > 0)
def verifyPubkey(self, pubkey_bytes: bytes) -> bool:
return verify_secp256k1_point(pubkey_bytes)
def isValidAddressHash(self, address_hash: bytes) -> bool:
hash_len = len(address_hash)
if hash_len == 20:
return True
def isValidPubkey(self, pubkey: bytes) -> bool:
try:
self.verifyPubkey(pubkey)
return True
except Exception:
return False
def verifySig(self, pubkey: bytes, signed_hash: bytes, sig: bytes) -> bool:
pubkey = PublicKey(pubkey)
return pubkey.verify(sig, signed_hash, hasher=None)
def sumKeys(self, ka: bytes, kb: bytes) -> bytes:
# TODO: Add to coincurve
return i2b((b2i(ka) + b2i(kb)) % ep.o)
def sumPubkeys(self, Ka: bytes, Kb: bytes) -> bytes:
return PublicKey.combine_keys([PublicKey(Ka), PublicKey(Kb)]).format()

View File

@@ -5,31 +5,25 @@
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php. # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
import json
import base64 import base64
import hashlib import hashlib
import json
import logging import logging
import traceback import traceback
from io import BytesIO from io import BytesIO
from basicswap.basicswap_util import ( from basicswap.contrib.test_framework import segwit_addr
getVoutByAddress,
getVoutByScriptPubKey, from basicswap.interface import (
) Curves)
from basicswap.contrib.test_framework import (
segwit_addr,
)
from basicswap.interface.base import (
Secp256k1Interface,
)
from basicswap.util import ( from basicswap.util import (
ensure, ensure,
b2h, i2b, b2i, i2h, make_int,
) b2h, i2b, b2i, i2h)
from basicswap.util.ecc import ( from basicswap.util.ecc import (
ep,
pointToCPK, CPKToPoint, pointToCPK, CPKToPoint,
) getSecretInt)
from basicswap.util.script import ( from basicswap.util.script import (
decodeScriptNum, decodeScriptNum,
getCompactSizeLen, getCompactSizeLen,
@@ -43,20 +37,16 @@ from basicswap.util.address import (
decodeAddress, decodeAddress,
pubkeyToAddress, pubkeyToAddress,
) )
from basicswap.util.crypto import (
hash160,
sha256,
)
from coincurve.keys import ( from coincurve.keys import (
PrivateKey, PrivateKey,
PublicKey, PublicKey)
) from coincurve.dleag import (
verify_secp256k1_point)
from coincurve.ecdsaotves import ( from coincurve.ecdsaotves import (
ecdsaotves_enc_sign, ecdsaotves_enc_sign,
ecdsaotves_enc_verify, ecdsaotves_enc_verify,
ecdsaotves_dec_sig, ecdsaotves_dec_sig,
ecdsaotves_rec_enc_key ecdsaotves_rec_enc_key)
)
from basicswap.contrib.test_framework.messages import ( from basicswap.contrib.test_framework.messages import (
COIN, COIN,
@@ -65,7 +55,8 @@ from basicswap.contrib.test_framework.messages import (
CTxIn, CTxIn,
CTxInWitness, CTxInWitness,
CTxOut, CTxOut,
) uint256_from_str)
from basicswap.contrib.test_framework.script import ( from basicswap.contrib.test_framework.script import (
CScript, CScriptOp, CScript, CScriptOp,
OP_IF, OP_ELSE, OP_ENDIF, OP_IF, OP_ELSE, OP_ENDIF,
@@ -77,12 +68,12 @@ from basicswap.contrib.test_framework.script import (
OP_HASH160, OP_EQUAL, OP_HASH160, OP_EQUAL,
SIGHASH_ALL, SIGHASH_ALL,
SegwitV0SignatureHash, SegwitV0SignatureHash,
) hash160)
from basicswap.basicswap_util import (
TxLockTypes
)
from basicswap.chainparams import Coins from basicswap.basicswap_util import (
TxLockTypes)
from basicswap.chainparams import CoinInterface, Coins
from basicswap.rpc import make_rpc_func, openrpc from basicswap.rpc import make_rpc_func, openrpc
@@ -118,58 +109,10 @@ def find_vout_for_address_from_txobj(tx_obj, addr: str) -> int:
raise RuntimeError("Vout not found for address: txid={}, addr={}".format(tx_obj['txid'], addr)) raise RuntimeError("Vout not found for address: txid={}, addr={}".format(tx_obj['txid'], addr))
def extractScriptLockScriptValues(script_bytes: bytes) -> (bytes, bytes): class BTCInterface(CoinInterface):
script_len = len(script_bytes) @staticmethod
ensure(script_len == 71, 'Bad script length') def curve_type():
o = 0 return Curves.secp256k1
ensure_op(script_bytes[o] == OP_2)
ensure_op(script_bytes[o + 1] == 33)
o += 2
pk1 = script_bytes[o: o + 33]
o += 33
ensure_op(script_bytes[o] == 33)
o += 1
pk2 = script_bytes[o: o + 33]
o += 33
ensure_op(script_bytes[o] == OP_2)
ensure_op(script_bytes[o + 1] == OP_CHECKMULTISIG)
return pk1, pk2
def extractScriptLockRefundScriptValues(script_bytes: bytes):
script_len = len(script_bytes)
ensure(script_len > 73, 'Bad script length')
ensure_op(script_bytes[0] == OP_IF)
ensure_op(script_bytes[1] == OP_2)
ensure_op(script_bytes[2] == 33)
pk1 = script_bytes[3: 3 + 33]
ensure_op(script_bytes[36] == 33)
pk2 = script_bytes[37: 37 + 33]
ensure_op(script_bytes[70] == OP_2)
ensure_op(script_bytes[71] == OP_CHECKMULTISIG)
ensure_op(script_bytes[72] == OP_ELSE)
o = 73
csv_val, nb = decodeScriptNum(script_bytes, o)
o += nb
ensure(script_len == o + 5 + 33, 'Bad script length') # Fails if script too long
ensure_op(script_bytes[o] == OP_CHECKSEQUENCEVERIFY)
o += 1
ensure_op(script_bytes[o] == OP_DROP)
o += 1
ensure_op(script_bytes[o] == 33)
o += 1
pk3 = script_bytes[o: o + 33]
o += 33
ensure_op(script_bytes[o] == OP_CHECKSIG)
o += 1
ensure_op(script_bytes[o] == OP_ENDIF)
return pk1, pk2, csv_val, pk3
class BTCInterface(Secp256k1Interface):
@staticmethod @staticmethod
def coin_type(): def coin_type():
@@ -206,6 +149,10 @@ class BTCInterface(Secp256k1Interface):
rv += output.nValue rv += output.nValue
return rv return rv
@staticmethod
def compareFeeRates(a, b) -> bool:
return abs(a - b) < 20
@staticmethod @staticmethod
def xmr_swap_a_lock_spend_tx_vsize() -> int: def xmr_swap_a_lock_spend_tx_vsize() -> int:
return 147 return 147
@@ -220,7 +167,7 @@ class BTCInterface(Secp256k1Interface):
@staticmethod @staticmethod
def getExpectedSequence(lockType: int, lockVal: int) -> int: def getExpectedSequence(lockType: int, lockVal: int) -> int:
ensure(lockVal >= 1, 'Bad lockVal') assert (lockVal >= 1), 'Bad lockVal'
if lockType == TxLockTypes.SEQUENCE_LOCK_BLOCKS: if lockType == TxLockTypes.SEQUENCE_LOCK_BLOCKS:
return lockVal return lockVal
if lockType == TxLockTypes.SEQUENCE_LOCK_TIME: if lockType == TxLockTypes.SEQUENCE_LOCK_TIME:
@@ -259,23 +206,6 @@ class BTCInterface(Secp256k1Interface):
self._log = self._sc.log if self._sc and self._sc.log else logging self._log = self._sc.log if self._sc and self._sc.log else logging
self._expect_seedid_hex = None self._expect_seedid_hex = None
def open_rpc(self, wallet=None):
return openrpc(self._rpcport, self._rpcauth, wallet=wallet, host=self._rpc_host)
def json_request(self, rpc_conn, method, params):
try:
v = rpc_conn.json_request(method, params)
r = json.loads(v.decode('utf-8'))
except Exception as ex:
traceback.print_exc()
raise ValueError('RPC Server Error ' + str(ex))
if 'error' in r and r['error'] is not None:
raise ValueError('RPC error ' + str(r['error']))
return r['result']
def close_rpc(self, rpc_conn):
rpc_conn.close()
def checkWallets(self) -> int: def checkWallets(self) -> int:
wallets = self.rpc('listwallets') wallets = self.rpc('listwallets')
@@ -293,6 +223,40 @@ class BTCInterface(Secp256k1Interface):
return len(wallets) return len(wallets)
def using_segwit(self) -> bool:
# Using btc native segwit
return self._use_segwit
def use_p2shp2wsh(self) -> bool:
# p2sh-p2wsh
return False
def get_connection_type(self):
return self._connection_type
def open_rpc(self, wallet=None):
return openrpc(self._rpcport, self._rpcauth, wallet=wallet, host=self._rpc_host)
def json_request(self, rpc_conn, method, params):
try:
v = rpc_conn.json_request(method, params)
r = json.loads(v.decode('utf-8'))
except Exception as ex:
traceback.print_exc()
raise ValueError('RPC Server Error ' + str(ex))
if 'error' in r and r['error'] is not None:
raise ValueError('RPC error ' + str(r['error']))
return r['result']
def close_rpc(self, rpc_conn):
rpc_conn.close()
def setConfTarget(self, new_conf_target: int) -> None:
ensure(new_conf_target >= 1 and new_conf_target < 33, 'Invalid conf_target value')
self._conf_target = new_conf_target
def testDaemonRPC(self, with_wallet=True) -> None: def testDaemonRPC(self, with_wallet=True) -> None:
self.rpc_wallet('getwalletinfo' if with_wallet else 'getblockchaininfo') self.rpc_wallet('getwalletinfo' if with_wallet else 'getblockchaininfo')
@@ -321,7 +285,7 @@ class BTCInterface(Secp256k1Interface):
max_tries = 5000 max_tries = 5000
for i in range(max_tries): for i in range(max_tries):
prev_block_header = self.rpc('getblockheader', [last_block_header['previousblockhash']]) prev_block_header = self.rpc('getblock', [last_block_header['previousblockhash']])
if prev_block_header['time'] <= time: if prev_block_header['time'] <= time:
return last_block_header if block_after else prev_block_header return last_block_header if block_after else prev_block_header
@@ -339,6 +303,9 @@ class BTCInterface(Secp256k1Interface):
rv['locked_utxos'] = len(self.rpc_wallet('listlockunspent')) rv['locked_utxos'] = len(self.rpc_wallet('listlockunspent'))
return rv return rv
def walletRestoreHeight(self) -> int:
return self._restore_height
def getWalletRestoreHeight(self) -> int: def getWalletRestoreHeight(self) -> int:
start_time = self.rpc_wallet('getwalletinfo')['keypoololdest'] start_time = self.rpc_wallet('getwalletinfo')['keypoololdest']
@@ -386,6 +353,18 @@ class BTCInterface(Secp256k1Interface):
self._log.debug('validateaddress failed: {}'.format(address)) self._log.debug('validateaddress failed: {}'.format(address))
return False return False
def isValidAddressHash(self, address_hash: bytes) -> bool:
hash_len = len(address_hash)
if hash_len == 20:
return True
def isValidPubkey(self, pubkey: bytes) -> bool:
try:
self.verifyPubkey(pubkey)
return True
except Exception:
return False
def isAddressMine(self, address: str, or_watch_only: bool = False) -> bool: def isAddressMine(self, address: str, or_watch_only: bool = False) -> bool:
addr_info = self.rpc_wallet('getaddressinfo', [address]) addr_info = self.rpc_wallet('getaddressinfo', [address])
if not or_watch_only: if not or_watch_only:
@@ -443,11 +422,11 @@ class BTCInterface(Secp256k1Interface):
return segwit_addr.encode(bech32_prefix, version, pkh) return segwit_addr.encode(bech32_prefix, version, pkh)
def pkh_to_address(self, pkh: bytes) -> str: def pkh_to_address(self, pkh: bytes) -> str:
# pkh is ripemd160(sha256(pk)) # pkh is hash160(pk)
assert (len(pkh) == 20) assert (len(pkh) == 20)
prefix = self.chainparams_network()['pubkey_address'] prefix = self.chainparams_network()['pubkey_address']
data = bytes((prefix,)) + pkh data = bytes((prefix,)) + pkh
checksum = sha256(sha256(data)) checksum = hashlib.sha256(hashlib.sha256(data).digest()).digest()
return b58encode(data + checksum[0:4]) return b58encode(data + checksum[0:4])
def sh_to_address(self, sh: bytes) -> str: def sh_to_address(self, sh: bytes) -> str:
@@ -473,6 +452,12 @@ class BTCInterface(Secp256k1Interface):
assert (len(pk) == 33) assert (len(pk) == 33)
return self.pkh_to_address(hash160(pk)) return self.pkh_to_address(hash160(pk))
def getNewSecretKey(self) -> bytes:
return i2b(getSecretInt())
def getPubkey(self, privkey):
return PublicKey.from_secret(privkey).format()
def getAddressHashFromKey(self, key: bytes) -> bytes: def getAddressHashFromKey(self, key: bytes) -> bytes:
pk = self.getPubkey(key) pk = self.getPubkey(key)
return hash160(pk) return hash160(pk)
@@ -480,6 +465,13 @@ class BTCInterface(Secp256k1Interface):
def getSeedHash(self, seed) -> bytes: def getSeedHash(self, seed) -> bytes:
return self.getAddressHashFromKey(seed)[::-1] return self.getAddressHashFromKey(seed)[::-1]
def verifyKey(self, k: bytes) -> bool:
i = b2i(k)
return (i < ep.o and i > 0)
def verifyPubkey(self, pubkey_bytes: bytes) -> bool:
return verify_secp256k1_point(pubkey_bytes)
def encodeKey(self, key_bytes: bytes) -> str: def encodeKey(self, key_bytes: bytes) -> str:
wif_prefix = self.chainparams_network()['key_prefix'] wif_prefix = self.chainparams_network()['key_prefix']
return toWIF(wif_prefix, key_bytes) return toWIF(wif_prefix, key_bytes)
@@ -499,6 +491,13 @@ class BTCInterface(Secp256k1Interface):
def decodeKey(self, k: str) -> bytes: def decodeKey(self, k: str) -> bytes:
return decodeWif(k) return decodeWif(k)
def sumKeys(self, ka, kb):
# TODO: Add to coincurve
return i2b((b2i(ka) + b2i(kb)) % ep.o)
def sumPubkeys(self, Ka, Kb):
return PublicKey.combine_keys([PublicKey(Ka), PublicKey(Kb)]).format()
def getScriptForPubkeyHash(self, pkh: bytes) -> CScript: def getScriptForPubkeyHash(self, pkh: bytes) -> CScript:
# p2wpkh # p2wpkh
return CScript([OP_0, pkh]) return CScript([OP_0, pkh])
@@ -509,6 +508,24 @@ class BTCInterface(Secp256k1Interface):
tx.deserialize(BytesIO(tx_bytes)) tx.deserialize(BytesIO(tx_bytes))
return tx return tx
def extractScriptLockScriptValues(self, script_bytes: bytes):
script_len = len(script_bytes)
ensure(script_len == 71, 'Bad script length')
o = 0
ensure_op(script_bytes[o] == OP_2)
ensure_op(script_bytes[o + 1] == 33)
o += 2
pk1 = script_bytes[o: o + 33]
o += 33
ensure_op(script_bytes[o] == 33)
o += 1
pk2 = script_bytes[o: o + 33]
o += 33
ensure_op(script_bytes[o] == OP_2)
ensure_op(script_bytes[o + 1] == OP_CHECKMULTISIG)
return pk1, pk2
def createSCLockTx(self, value: int, script: bytearray, vkbv: bytes = None) -> bytes: def createSCLockTx(self, value: int, script: bytearray, vkbv: bytes = None) -> bytes:
tx = CTransaction() tx = CTransaction()
tx.nVersion = self.txVersion() tx.nVersion = self.txVersion()
@@ -518,6 +535,37 @@ class BTCInterface(Secp256k1Interface):
def fundSCLockTx(self, tx_bytes, feerate, vkbv=None): def fundSCLockTx(self, tx_bytes, feerate, vkbv=None):
return self.fundTx(tx_bytes, feerate) return self.fundTx(tx_bytes, feerate)
def extractScriptLockRefundScriptValues(self, script_bytes: bytes):
script_len = len(script_bytes)
ensure(script_len > 73, 'Bad script length')
ensure_op(script_bytes[0] == OP_IF)
ensure_op(script_bytes[1] == OP_2)
ensure_op(script_bytes[2] == 33)
pk1 = script_bytes[3: 3 + 33]
ensure_op(script_bytes[36] == 33)
pk2 = script_bytes[37: 37 + 33]
ensure_op(script_bytes[70] == OP_2)
ensure_op(script_bytes[71] == OP_CHECKMULTISIG)
ensure_op(script_bytes[72] == OP_ELSE)
o = 73
csv_val, nb = decodeScriptNum(script_bytes, o)
o += nb
ensure(script_len == o + 5 + 33, 'Bad script length') # Fails if script too long
ensure_op(script_bytes[o] == OP_CHECKSEQUENCEVERIFY)
o += 1
ensure_op(script_bytes[o] == OP_DROP)
o += 1
ensure_op(script_bytes[o] == 33)
o += 1
pk3 = script_bytes[o: o + 33]
o += 33
ensure_op(script_bytes[o] == OP_CHECKSIG)
o += 1
ensure_op(script_bytes[o] == OP_ENDIF)
return pk1, pk2, csv_val, pk3
def genScriptLockRefundTxScript(self, Kal, Kaf, csv_val) -> CScript: def genScriptLockRefundTxScript(self, Kal, Kaf, csv_val) -> CScript:
Kal_enc = Kal if len(Kal) == 33 else self.encodePubkey(Kal) Kal_enc = Kal if len(Kal) == 33 else self.encodePubkey(Kal)
@@ -609,7 +657,7 @@ class BTCInterface(Secp256k1Interface):
ensure(locked_n is not None, 'Output not found in tx') ensure(locked_n is not None, 'Output not found in tx')
locked_coin = tx_lock_refund.vout[locked_n].nValue locked_coin = tx_lock_refund.vout[locked_n].nValue
A, B, lock2_value, C = extractScriptLockRefundScriptValues(script_lock_refund) A, B, lock2_value, C = self.extractScriptLockRefundScriptValues(script_lock_refund)
tx_lock_refund.rehash() tx_lock_refund.rehash()
tx_lock_refund_hash_int = tx_lock_refund.sha256 tx_lock_refund_hash_int = tx_lock_refund.sha256
@@ -696,7 +744,7 @@ class BTCInterface(Secp256k1Interface):
ensure(locked_coin == swap_value, 'Bad locked value') ensure(locked_coin == swap_value, 'Bad locked value')
# Check script # Check script
A, B = extractScriptLockScriptValues(script_out) A, B = self.extractScriptLockScriptValues(script_out)
ensure(A == Kal, 'Bad script pubkey') ensure(A == Kal, 'Bad script pubkey')
ensure(B == Kaf, 'Bad script pubkey') ensure(B == Kaf, 'Bad script pubkey')
@@ -709,7 +757,7 @@ class BTCInterface(Secp256k1Interface):
for pi in tx.vin: for pi in tx.vin:
ptx = self.rpc('getrawtransaction', [i2h(pi.prevout.hash), True]) ptx = self.rpc('getrawtransaction', [i2h(pi.prevout.hash), True])
prevout = ptx['vout'][pi.prevout.n] prevout = ptx['vout'][pi.prevout.n]
inputs_value += self.make_int(prevout['value']) inputs_value += make_int(prevout['value'])
prevout_type = prevout['scriptPubKey']['type'] prevout_type = prevout['scriptPubKey']['type']
if prevout_type == 'witness_v0_keyhash': if prevout_type == 'witness_v0_keyhash':
@@ -764,7 +812,7 @@ class BTCInterface(Secp256k1Interface):
locked_coin = tx.vout[locked_n].nValue locked_coin = tx.vout[locked_n].nValue
# Check script and values # Check script and values
A, B, csv_val, C = extractScriptLockRefundScriptValues(script_out) A, B, csv_val, C = self.extractScriptLockRefundScriptValues(script_out)
ensure(A == Kal, 'Bad script pubkey') ensure(A == Kal, 'Bad script pubkey')
ensure(B == Kaf, 'Bad script pubkey') ensure(B == Kaf, 'Bad script pubkey')
ensure(csv_val == csv_val_expect, 'Bad script csv value') ensure(csv_val == csv_val_expect, 'Bad script csv value')
@@ -876,30 +924,27 @@ class BTCInterface(Secp256k1Interface):
return True return True
def signTx(self, key_bytes: bytes, tx_bytes: bytes, input_n: int, prevout_script: bytes, prevout_value: int) -> bytes: def signTx(self, key_bytes, tx_bytes, input_n, prevout_script, prevout_value):
tx = self.loadTx(tx_bytes) tx = self.loadTx(tx_bytes)
sig_hash = SegwitV0SignatureHash(prevout_script, tx, input_n, SIGHASH_ALL, prevout_value) sig_hash = SegwitV0SignatureHash(prevout_script, tx, input_n, SIGHASH_ALL, prevout_value)
eck = PrivateKey(key_bytes) eck = PrivateKey(key_bytes)
return eck.sign(sig_hash, hasher=None) + bytes((SIGHASH_ALL,)) return eck.sign(sig_hash, hasher=None) + bytes((SIGHASH_ALL,))
def signTxOtVES(self, key_sign: bytes, pubkey_encrypt: bytes, tx_bytes: bytes, input_n: int, prevout_script: bytes, prevout_value: int) -> bytes: def signTxOtVES(self, key_sign, pubkey_encrypt, tx_bytes, input_n, prevout_script, prevout_value):
tx = self.loadTx(tx_bytes) tx = self.loadTx(tx_bytes)
sig_hash = SegwitV0SignatureHash(prevout_script, tx, input_n, SIGHASH_ALL, prevout_value) sig_hash = SegwitV0SignatureHash(prevout_script, tx, input_n, SIGHASH_ALL, prevout_value)
return ecdsaotves_enc_sign(key_sign, pubkey_encrypt, sig_hash) return ecdsaotves_enc_sign(key_sign, pubkey_encrypt, sig_hash)
def verifyTxOtVES(self, tx_bytes: bytes, ct: bytes, Ks: bytes, Ke: bytes, input_n: int, prevout_script: bytes, prevout_value): def verifyTxOtVES(self, tx_bytes, ct, Ks, Ke, input_n, prevout_script, prevout_value):
tx = self.loadTx(tx_bytes) tx = self.loadTx(tx_bytes)
sig_hash = SegwitV0SignatureHash(prevout_script, tx, input_n, SIGHASH_ALL, prevout_value) sig_hash = SegwitV0SignatureHash(prevout_script, tx, input_n, SIGHASH_ALL, prevout_value)
return ecdsaotves_enc_verify(Ks, Ke, sig_hash, ct) return ecdsaotves_enc_verify(Ks, Ke, sig_hash, ct)
def decryptOtVES(self, k: bytes, esig: bytes) -> bytes: def decryptOtVES(self, k, esig):
return ecdsaotves_dec_sig(k, esig) + bytes((SIGHASH_ALL,)) return ecdsaotves_dec_sig(k, esig) + bytes((SIGHASH_ALL,))
def recoverEncKey(self, esig, sig, K):
return ecdsaotves_rec_enc_key(K, esig, sig[:-1]) # Strip sighash type
def verifyTxSig(self, tx_bytes: bytes, sig: bytes, K: bytes, input_n: int, prevout_script: bytes, prevout_value: int) -> bool: def verifyTxSig(self, tx_bytes: bytes, sig: bytes, K: bytes, input_n: int, prevout_script: bytes, prevout_value: int) -> bool:
tx = self.loadTx(tx_bytes) tx = self.loadTx(tx_bytes)
sig_hash = SegwitV0SignatureHash(prevout_script, tx, input_n, SIGHASH_ALL, prevout_value) sig_hash = SegwitV0SignatureHash(prevout_script, tx, input_n, SIGHASH_ALL, prevout_value)
@@ -907,7 +952,11 @@ class BTCInterface(Secp256k1Interface):
pubkey = PublicKey(K) pubkey = PublicKey(K)
return pubkey.verify(sig[: -1], sig_hash, hasher=None) # Pop the hashtype byte return pubkey.verify(sig[: -1], sig_hash, hasher=None) # Pop the hashtype byte
def fundTx(self, tx: bytes, feerate) -> bytes: def verifySig(self, pubkey, signed_hash, sig):
pubkey = PublicKey(pubkey)
return pubkey.verify(sig, signed_hash, hasher=None)
def fundTx(self, tx, feerate):
feerate_str = self.format_amount(feerate) feerate_str = self.format_amount(feerate)
# TODO: unlock unspents if bid cancelled # TODO: unlock unspents if bid cancelled
options = { options = {
@@ -917,7 +966,7 @@ class BTCInterface(Secp256k1Interface):
rv = self.rpc_wallet('fundrawtransaction', [tx.hex(), options]) rv = self.rpc_wallet('fundrawtransaction', [tx.hex(), options])
return bytes.fromhex(rv['hex']) return bytes.fromhex(rv['hex'])
def listInputs(self, tx_bytes: bytes): def listInputs(self, tx_bytes):
tx = self.loadTx(tx_bytes) tx = self.loadTx(tx_bytes)
all_locked = self.rpc_wallet('listlockunspent') all_locked = self.rpc_wallet('listlockunspent')
@@ -969,20 +1018,20 @@ class BTCInterface(Secp256k1Interface):
return hash160(K) return hash160(K)
def getScriptDest(self, script): def getScriptDest(self, script):
return CScript([OP_0, sha256(script)]) return CScript([OP_0, hashlib.sha256(script).digest()])
def getScriptScriptSig(self, script: bytes) -> bytes: def getScriptScriptSig(self, script: bytes) -> bytes:
return bytes() return bytes()
def getP2SHP2WSHDest(self, script): def getP2SHP2WSHDest(self, script):
script_hash = sha256(script) script_hash = hashlib.sha256(script).digest()
assert len(script_hash) == 32 assert len(script_hash) == 32
p2wsh_hash = hash160(CScript([OP_0, script_hash])) p2wsh_hash = hash160(CScript([OP_0, script_hash]))
assert len(p2wsh_hash) == 20 assert len(p2wsh_hash) == 20
return CScript([OP_HASH160, p2wsh_hash, OP_EQUAL]) return CScript([OP_HASH160, p2wsh_hash, OP_EQUAL])
def getP2SHP2WSHScriptSig(self, script): def getP2SHP2WSHScriptSig(self, script):
script_hash = sha256(script) script_hash = hashlib.sha256(script).digest()
assert len(script_hash) == 32 assert len(script_hash) == 32
return CScript([CScript([OP_0, script_hash, ]), ]) return CScript([CScript([OP_0, script_hash, ]), ])
@@ -1001,7 +1050,7 @@ class BTCInterface(Secp256k1Interface):
def getWalletTransaction(self, txid: bytes): def getWalletTransaction(self, txid: bytes):
try: try:
return bytes.fromhex(self.rpc_wallet('gettransaction', [txid.hex()])) return bytes.fromhex(self.rpc('gettransaction', [txid.hex()]))
except Exception as ex: except Exception as ex:
# TODO: filter errors # TODO: filter errors
return None return None
@@ -1023,11 +1072,11 @@ class BTCInterface(Secp256k1Interface):
tx.wit.vtxinwit.clear() tx.wit.vtxinwit.clear()
return tx.serialize() return tx.serialize()
def extractLeaderSig(self, tx_bytes: bytes) -> bytes: def extractLeaderSig(self, tx_bytes) -> bytes:
tx = self.loadTx(tx_bytes) tx = self.loadTx(tx_bytes)
return tx.wit.vtxinwit[0].scriptWitness.stack[1] return tx.wit.vtxinwit[0].scriptWitness.stack[1]
def extractFollowerSig(self, tx_bytes: bytes) -> bytes: def extractFollowerSig(self, tx_bytes) -> bytes:
tx = self.loadTx(tx_bytes) tx = self.loadTx(tx_bytes)
return tx.wit.vtxinwit[0].scriptWitness.stack[2] return tx.wit.vtxinwit[0].scriptWitness.stack[2]
@@ -1041,7 +1090,7 @@ class BTCInterface(Secp256k1Interface):
def encodeSharedAddress(self, Kbv, Kbs): def encodeSharedAddress(self, Kbv, Kbs):
return self.pubkey_to_segwit_address(Kbs) return self.pubkey_to_segwit_address(Kbs)
def publishBLockTx(self, kbv, Kbs, output_amount, feerate, unlock_time: int = 0) -> bytes: def publishBLockTx(self, kbv, Kbs, output_amount, feerate, delay_for: int = 10, unlock_time: int = 0) -> bytes:
b_lock_tx = self.createBLockTx(Kbs, output_amount) b_lock_tx = self.createBLockTx(Kbs, output_amount)
b_lock_tx = self.fundTx(b_lock_tx, feerate) b_lock_tx = self.fundTx(b_lock_tx, feerate)
@@ -1050,6 +1099,9 @@ class BTCInterface(Secp256k1Interface):
return bytes.fromhex(self.publishTx(b_lock_tx)) return bytes.fromhex(self.publishTx(b_lock_tx))
def recoverEncKey(self, esig, sig, K):
return ecdsaotves_rec_enc_key(K, esig, sig[:-1]) # Strip sighash type
def getTxVSize(self, tx, add_bytes: int = 0, add_witness_bytes: int = 0) -> int: def getTxVSize(self, tx, add_bytes: int = 0, add_witness_bytes: int = 0) -> int:
wsf = self.witnessScaleFactor() wsf = self.witnessScaleFactor()
len_full = len(tx.serialize_with_witness()) + add_bytes + add_witness_bytes len_full = len(tx.serialize_with_witness()) + add_bytes + add_witness_bytes
@@ -1082,7 +1134,7 @@ class BTCInterface(Secp256k1Interface):
self._log.info(f'BLockSpendTx fee_rate, vsize, fee: {fee_rate}, {vsize}, {pay_fee}.') self._log.info(f'BLockSpendTx fee_rate, vsize, fee: {fee_rate}, {vsize}, {pay_fee}.')
return pay_fee return pay_fee
def spendBLockTx(self, chain_b_lock_txid: bytes, address_to: str, kbv: bytes, kbs: bytes, cb_swap_value: int, b_fee: int, restore_height: int, lock_tx_vout=None) -> bytes: def spendBLockTx(self, chain_b_lock_txid: bytes, address_to: str, kbv: bytes, kbs: bytes, cb_swap_value: int, b_fee: int, restore_height: int) -> bytes:
self._log.info('spendBLockTx %s:\n', chain_b_lock_txid.hex()) self._log.info('spendBLockTx %s:\n', chain_b_lock_txid.hex())
wtx = self.rpc_wallet('gettransaction', [chain_b_lock_txid.hex(), ]) wtx = self.rpc_wallet('gettransaction', [chain_b_lock_txid.hex(), ])
lock_tx = self.loadTx(bytes.fromhex(wtx['hex'])) lock_tx = self.loadTx(bytes.fromhex(wtx['hex']))
@@ -1097,7 +1149,7 @@ class BTCInterface(Secp256k1Interface):
tx.nVersion = self.txVersion() tx.nVersion = self.txVersion()
script_lock = self.getScriptForPubkeyHash(Kbs) script_lock = self.getScriptForPubkeyHash(Kbs)
chain_b_lock_txid_int = b2i(chain_b_lock_txid) chain_b_lock_txid_int = uint256_from_str(chain_b_lock_txid[::-1])
tx.vin.append(CTxIn(COutPoint(chain_b_lock_txid_int, locked_n), tx.vin.append(CTxIn(COutPoint(chain_b_lock_txid_int, locked_n),
nSequence=0, nSequence=0,
@@ -1119,11 +1171,11 @@ class BTCInterface(Secp256k1Interface):
addr_info = self.rpc_wallet('getaddressinfo', [address]) addr_info = self.rpc_wallet('getaddressinfo', [address])
return addr_info['iswatchonly'] return addr_info['iswatchonly']
def getSCLockScriptAddress(self, lock_script: bytes) -> str: def getSCLockScriptAddress(self, lock_script):
lock_tx_dest = self.getScriptDest(lock_script) lock_tx_dest = self.getScriptDest(lock_script)
return self.encodeScriptDest(lock_tx_dest) return self.encodeScriptDest(lock_tx_dest)
def getLockTxHeight(self, txid, dest_address, bid_amount, rescan_from, find_index: bool = False, vout: int = -1): def getLockTxHeight(self, txid, dest_address, bid_amount, rescan_from, find_index: bool = False):
# Add watchonly address and rescan if required # Add watchonly address and rescan if required
if not self.isAddressMine(dest_address, or_watch_only=True): if not self.isAddressMine(dest_address, or_watch_only=True):
@@ -1192,30 +1244,30 @@ class BTCInterface(Secp256k1Interface):
'vout': utxo['vout']}) 'vout': utxo['vout']})
return rv, chain_height return rv, chain_height
def withdrawCoin(self, value: float, addr_to: str, subfee: bool): def withdrawCoin(self, value, addr_to, subfee):
params = [addr_to, value, '', '', subfee, True, self._conf_target] params = [addr_to, value, '', '', subfee, True, self._conf_target]
return self.rpc_wallet('sendtoaddress', params) return self.rpc_wallet('sendtoaddress', params)
def signCompact(self, k, message: str) -> bytes: def signCompact(self, k, message):
message_hash = sha256(bytes(message, 'utf-8')) message_hash = hashlib.sha256(bytes(message, 'utf-8')).digest()
privkey = PrivateKey(k) privkey = PrivateKey(k)
return privkey.sign_recoverable(message_hash, hasher=None)[:64] return privkey.sign_recoverable(message_hash, hasher=None)[:64]
def signRecoverable(self, k, message: str) -> bytes: def signRecoverable(self, k, message):
message_hash = sha256(bytes(message, 'utf-8')) message_hash = hashlib.sha256(bytes(message, 'utf-8')).digest()
privkey = PrivateKey(k) privkey = PrivateKey(k)
return privkey.sign_recoverable(message_hash, hasher=None) return privkey.sign_recoverable(message_hash, hasher=None)
def verifyCompactSig(self, K, message: str, sig) -> None: def verifyCompactSig(self, K, message, sig):
message_hash = sha256(bytes(message, 'utf-8')) message_hash = hashlib.sha256(bytes(message, 'utf-8')).digest()
pubkey = PublicKey(K) pubkey = PublicKey(K)
rv = pubkey.verify_compact(sig, message_hash, hasher=None) rv = pubkey.verify_compact(sig, message_hash, hasher=None)
assert (rv is True) assert (rv is True)
def verifySigAndRecover(self, sig, message: str) -> bytes: def verifySigAndRecover(self, sig, message):
message_hash = sha256(bytes(message, 'utf-8')) message_hash = hashlib.sha256(bytes(message, 'utf-8')).digest()
pubkey = PublicKey.from_signature_and_message(sig, message_hash, hasher=None) pubkey = PublicKey.from_signature_and_message(sig, message_hash, hasher=None)
return pubkey.format() return pubkey.format()
@@ -1224,7 +1276,7 @@ class BTCInterface(Secp256k1Interface):
message_magic = self.chainparams()['message_magic'] message_magic = self.chainparams()['message_magic']
message_bytes = SerialiseNumCompact(len(message_magic)) + bytes(message_magic, 'utf-8') + SerialiseNumCompact(len(message)) + bytes(message, 'utf-8') message_bytes = SerialiseNumCompact(len(message_magic)) + bytes(message_magic, 'utf-8') + SerialiseNumCompact(len(message)) + bytes(message, 'utf-8')
message_hash = sha256(sha256(message_bytes)) message_hash = hashlib.sha256(hashlib.sha256(message_bytes).digest()).digest()
signature_bytes = base64.b64decode(signature) signature_bytes = base64.b64decode(signature)
rec_id = (signature_bytes[0] - 27) & 3 rec_id = (signature_bytes[0] - 27) & 3
signature_bytes = signature_bytes[1:] + bytes((rec_id,)) signature_bytes = signature_bytes[1:] + bytes((rec_id,))
@@ -1242,6 +1294,40 @@ class BTCInterface(Secp256k1Interface):
def showLockTransfers(self, kbv, Kbs, restore_height): def showLockTransfers(self, kbv, Kbs, restore_height):
raise ValueError('Unimplemented') raise ValueError('Unimplemented')
def getLockTxSwapOutputValue(self, bid, xmr_swap):
return bid.amount
def getLockRefundTxSwapOutputValue(self, bid, xmr_swap):
return xmr_swap.a_swap_refund_value
def getLockRefundTxSwapOutput(self, xmr_swap):
# Only one prevout exists
return 0
def getScriptLockTxDummyWitness(self, script: bytes):
return [
b'',
bytes(72),
bytes(72),
bytes(len(script))
]
def getScriptLockRefundSpendTxDummyWitness(self, script: bytes):
return [
b'',
bytes(72),
bytes(72),
bytes((1,)),
bytes(len(script))
]
def getScriptLockRefundSwipeTxDummyWitness(self, script: bytes):
return [
bytes(72),
b'',
bytes(len(script))
]
def getWitnessStackSerialisedLength(self, witness_stack): def getWitnessStackSerialisedLength(self, witness_stack):
length = getCompactSizeLen(len(witness_stack)) length = getCompactSizeLen(len(witness_stack))
for e in witness_stack: for e in witness_stack:
@@ -1290,7 +1376,7 @@ class BTCInterface(Secp256k1Interface):
unspent_addr = dict() unspent_addr = dict()
unspent = self.rpc_wallet('listunspent') unspent = self.rpc_wallet('listunspent')
for u in unspent: for u in unspent:
if u.get('spendable', False) is False: if u['spendable'] is not True:
continue continue
if 'address' not in u: if 'address' not in u:
continue continue
@@ -1323,6 +1409,7 @@ class BTCInterface(Secp256k1Interface):
def getProofOfFunds(self, amount_for, extra_commit_bytes): def getProofOfFunds(self, amount_for, extra_commit_bytes):
# TODO: Lock unspent and use same output/s to fund bid # TODO: Lock unspent and use same output/s to fund bid
unspent_addr = self.getUnspentsByAddr() unspent_addr = self.getUnspentsByAddr()
sign_for_addr = None sign_for_addr = None
for addr, value in unspent_addr.items(): for addr, value in unspent_addr.items():
if value >= amount_for: if value >= amount_for:
@@ -1344,12 +1431,6 @@ class BTCInterface(Secp256k1Interface):
prove_utxos = [] # TODO: Send specific utxos prove_utxos = [] # TODO: Send specific utxos
return (sign_for_addr, signature, prove_utxos) return (sign_for_addr, signature, prove_utxos)
def encodeProofUtxos(self, proof_utxos):
packed_utxos = bytes()
for utxo in proof_utxos:
packed_utxos += utxo[0] + utxo[1].to_bytes(2, 'big')
return packed_utxos
def decodeProofUtxos(self, msg_utxos): def decodeProofUtxos(self, msg_utxos):
proof_utxos = [] proof_utxos = []
if len(msg_utxos) > 0: if len(msg_utxos) > 0:
@@ -1379,7 +1460,7 @@ class BTCInterface(Secp256k1Interface):
return True return True
return False return False
def isWalletEncryptedLocked(self) -> (bool, bool): def isWalletEncryptedLocked(self):
wallet_info = self.rpc_wallet('getwalletinfo') wallet_info = self.rpc_wallet('getwalletinfo')
encrypted = 'unlocked_until' in wallet_info encrypted = 'unlocked_until' in wallet_info
locked = encrypted and wallet_info['unlocked_until'] <= 0 locked = encrypted and wallet_info['unlocked_until'] <= 0
@@ -1422,7 +1503,7 @@ class BTCInterface(Secp256k1Interface):
return CScript([OP_HASH160, script_hash, OP_EQUAL]) return CScript([OP_HASH160, script_hash, OP_EQUAL])
def get_p2wsh_script_pubkey(self, script: bytearray) -> bytearray: def get_p2wsh_script_pubkey(self, script: bytearray) -> bytearray:
return CScript([OP_0, sha256(script)]) return CScript([OP_0, hashlib.sha256(script).digest()])
def findTxnByHash(self, txid_hex: str): def findTxnByHash(self, txid_hex: str):
# Only works for wallet txns # Only works for wallet txns
@@ -1435,10 +1516,10 @@ class BTCInterface(Secp256k1Interface):
return {'txid': txid_hex, 'amount': 0, 'height': rv['blockheight']} return {'txid': txid_hex, 'amount': 0, 'height': rv['blockheight']}
return None return None
def createRedeemTxn(self, prevout, output_addr: str, output_value: int, txn_script: bytes = None) -> str: def createRedeemTxn(self, prevout, output_addr: str, output_value: int) -> str:
tx = CTransaction() tx = CTransaction()
tx.nVersion = self.txVersion() tx.nVersion = self.txVersion()
prev_txid = b2i(bytes.fromhex(prevout['txid'])) prev_txid = uint256_from_str(bytes.fromhex(prevout['txid'])[::-1])
tx.vin.append(CTxIn(COutPoint(prev_txid, prevout['vout']))) tx.vin.append(CTxIn(COutPoint(prev_txid, prevout['vout'])))
pkh = self.decodeAddress(output_addr) pkh = self.decodeAddress(output_addr)
script = self.getScriptForPubkeyHash(pkh) script = self.getScriptForPubkeyHash(pkh)
@@ -1446,11 +1527,11 @@ class BTCInterface(Secp256k1Interface):
tx.rehash() tx.rehash()
return tx.serialize().hex() return tx.serialize().hex()
def createRefundTxn(self, prevout, output_addr: str, output_value: int, locktime: int, sequence: int, txn_script: bytes = None) -> str: def createRefundTxn(self, prevout, output_addr: str, output_value: int, locktime: int, sequence: int) -> str:
tx = CTransaction() tx = CTransaction()
tx.nVersion = self.txVersion() tx.nVersion = self.txVersion()
tx.nLockTime = locktime tx.nLockTime = locktime
prev_txid = b2i(bytes.fromhex(prevout['txid'])) prev_txid = uint256_from_str(bytes.fromhex(prevout['txid'])[::-1])
tx.vin.append(CTxIn(COutPoint(prev_txid, prevout['vout']), nSequence=sequence,)) tx.vin.append(CTxIn(COutPoint(prev_txid, prevout['vout']), nSequence=sequence,))
pkh = self.decodeAddress(output_addr) pkh = self.decodeAddress(output_addr)
script = self.getScriptForPubkeyHash(pkh) script = self.getScriptForPubkeyHash(pkh)
@@ -1470,30 +1551,6 @@ class BTCInterface(Secp256k1Interface):
tx_vsize += 323 if redeem else 287 tx_vsize += 323 if redeem else 287
return tx_vsize return tx_vsize
def find_prevout_info(self, txn_hex: str, txn_script: bytes):
txjs = self.rpc('decoderawtransaction', [txn_hex])
if self.using_segwit():
p2wsh = self.getScriptDest(txn_script)
n = getVoutByScriptPubKey(txjs, p2wsh.hex())
else:
addr_to = self.encode_p2sh(txn_script)
n = getVoutByAddress(txjs, addr_to)
return {
'txid': txjs['txid'],
'vout': n,
'scriptPubKey': txjs['vout'][n]['scriptPubKey']['hex'],
'redeemScript': txn_script.hex(),
'amount': txjs['vout'][n]['value']
}
def isTxExistsError(self, err_str: str) -> bool:
return 'Transaction already in block chain' in err_str
def isTxNonFinalError(self, err_str: str) -> bool:
return 'non-BIP68-final' in err_str or 'non-final' in err_str
def testBTCInterface(): def testBTCInterface():
print('TODO: testBTCInterface') print('TODO: testBTCInterface')

View File

@@ -1,4 +0,0 @@
from .dcr import DCRInterface
__all__ = ['DCRInterface',]

File diff suppressed because it is too large Load Diff

View File

@@ -1,204 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2024 tecnovert
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
import copy
from enum import IntEnum
from basicswap.util.crypto import blake256
from basicswap.util.integer import decode_compactsize, encode_compactsize
class TxSerializeType(IntEnum):
Full = 0
NoWitness = 1
OnlyWitness = 2
class SigHashType(IntEnum):
SigHashAll = 0x1
SigHashNone = 0x2
SigHashSingle = 0x3
SigHashAnyOneCanPay = 0x80
SigHashMask = 0x1f
class SignatureType(IntEnum):
STEcdsaSecp256k1 = 0
STEd25519 = 1
STSchnorrSecp256k1 = 2
class COutPoint:
__slots__ = ('hash', 'n', 'tree')
def __init__(self, hash=0, n=0, tree=0):
self.hash = hash
self.n = n
self.tree = tree
def get_hash(self) -> bytes:
return self.hash.to_bytes(32, 'big')
class CTxIn:
__slots__ = ('prevout', 'sequence',
'value_in', 'block_height', 'block_index', 'signature_script') # Witness
def __init__(self, prevout=COutPoint(), sequence=0):
self.prevout = prevout
self.sequence = sequence
self.value_in = -1
self.block_height = 0
self.block_index = 0xffffffff
self.signature_script = bytes()
class CTxOut:
__slots__ = ('value', 'version', 'script_pubkey')
def __init__(self, value=0, script_pubkey=bytes()):
self.value = value
self.version = 0
self.script_pubkey = script_pubkey
class CTransaction:
__slots__ = ('hash', 'version', 'vin', 'vout', 'locktime', 'expiry')
def __init__(self, tx=None):
if tx is None:
self.version = 1
self.vin = []
self.vout = []
self.locktime = 0
self.expiry = 0
else:
self.version = tx.version
self.vin = copy.deepcopy(tx.vin)
self.vout = copy.deepcopy(tx.vout)
self.locktime = tx.locktime
self.expiry = tx.expiry
def deserialize(self, data: bytes) -> None:
version = int.from_bytes(data[:4], 'little')
self.version = version & 0xffff
ser_type: int = version >> 16
o = 4
if ser_type == TxSerializeType.Full or ser_type == TxSerializeType.NoWitness:
num_txin, nb = decode_compactsize(data, o)
o += nb
for i in range(num_txin):
txi = CTxIn()
txi.prevout = COutPoint()
txi.prevout.hash = int.from_bytes(data[o:o + 32], 'little')
o += 32
txi.prevout.n = int.from_bytes(data[o:o + 4], 'little')
o += 4
txi.prevout.tree = data[o]
o += 1
txi.sequence = int.from_bytes(data[o:o + 4], 'little')
o += 4
self.vin.append(txi)
num_txout, nb = decode_compactsize(data, o)
o += nb
for i in range(num_txout):
txo = CTxOut()
txo.value = int.from_bytes(data[o:o + 8], 'little')
o += 8
txo.version = int.from_bytes(data[o:o + 2], 'little')
o += 2
script_bytes, nb = decode_compactsize(data, o)
o += nb
txo.script_pubkey = data[o:o + script_bytes]
o += script_bytes
self.vout.append(txo)
self.locktime = int.from_bytes(data[o:o + 4], 'little')
o += 4
self.expiry = int.from_bytes(data[o:o + 4], 'little')
o += 4
if ser_type == TxSerializeType.NoWitness:
return
num_wit_scripts, nb = decode_compactsize(data, o)
o += nb
if ser_type == TxSerializeType.OnlyWitness:
self.vin = [CTxIn() for _ in range(num_wit_scripts)]
else:
if num_wit_scripts != len(self.vin):
raise ValueError('non equal witness and prefix txin quantities')
for i in range(num_wit_scripts):
txi = self.vin[i]
txi.value_in = int.from_bytes(data[o:o + 8], 'little')
o += 8
txi.block_height = int.from_bytes(data[o:o + 4], 'little')
o += 4
txi.block_index = int.from_bytes(data[o:o + 4], 'little')
o += 4
script_bytes, nb = decode_compactsize(data, o)
o += nb
txi.signature_script = data[o:o + script_bytes]
o += script_bytes
def serialize(self, ser_type=TxSerializeType.Full) -> bytes:
data = bytes()
version = (self.version & 0xffff) | (ser_type << 16)
data += version.to_bytes(4, 'little')
if ser_type == TxSerializeType.Full or ser_type == TxSerializeType.NoWitness:
data += encode_compactsize(len(self.vin))
for txi in self.vin:
data += txi.prevout.hash.to_bytes(32, 'little')
data += txi.prevout.n.to_bytes(4, 'little')
data += txi.prevout.tree.to_bytes(1, 'little')
data += txi.sequence.to_bytes(4, 'little')
data += encode_compactsize(len(self.vout))
for txo in self.vout:
data += txo.value.to_bytes(8, 'little')
data += txo.version.to_bytes(2, 'little')
data += encode_compactsize(len(txo.script_pubkey))
data += txo.script_pubkey
data += self.locktime.to_bytes(4, 'little')
data += self.expiry.to_bytes(4, 'little')
if ser_type == TxSerializeType.Full or ser_type == TxSerializeType.OnlyWitness:
data += encode_compactsize(len(self.vin))
for txi in self.vin:
tc_value_in = txi.value_in & 0xffffffffffffffff # Convert negative values
data += tc_value_in.to_bytes(8, 'little')
data += txi.block_height.to_bytes(4, 'little')
data += txi.block_index.to_bytes(4, 'little')
data += encode_compactsize(len(txi.signature_script))
data += txi.signature_script
return data
def TxHash(self) -> bytes:
return blake256(self.serialize(TxSerializeType.NoWitness))[::-1]
def TxHashWitness(self) -> bytes:
raise ValueError('todo')
def TxHashFull(self) -> bytes:
raise ValueError('todo')
def findOutput(tx, script_pk: bytes):
for i in range(len(tx.vout)):
if tx.vout[i].script_pubkey == script_pk:
return i
return None

View File

@@ -1,47 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2024 tecnovert
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
import json
import traceback
from basicswap.rpc import Jsonrpc
def callrpc(rpc_port, auth, method, params=[], host='127.0.0.1'):
try:
url = 'http://{}@{}:{}/'.format(auth, host, rpc_port)
x = Jsonrpc(url)
x.__handler = None
v = x.json_request(method, params)
x.close()
r = json.loads(v.decode('utf-8'))
except Exception as ex:
traceback.print_exc()
raise ValueError('RPC server error ' + str(ex) + ', method: ' + method)
if 'error' in r and r['error'] is not None:
raise ValueError('RPC error ' + str(r['error']))
return r['result']
def openrpc(rpc_port, auth, host='127.0.0.1'):
try:
url = 'http://{}@{}:{}/'.format(auth, host, rpc_port)
return Jsonrpc(url)
except Exception as ex:
traceback.print_exc()
raise ValueError('RPC error ' + str(ex))
def make_rpc_func(port, auth, host='127.0.0.1'):
port = port
auth = auth
host = host
def rpc_func(method, params=None):
nonlocal port, auth, host
return callrpc(port, auth, method, params, host)
return rpc_func

View File

@@ -1,50 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2024 tecnovert
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
OP_0 = 0x00
OP_DATA_1 = 0x01
OP_1NEGATE = 0x4f
OP_1 = 0x51
OP_IF = 0x63
OP_ELSE = 0x67
OP_ENDIF = 0x68
OP_DROP = 0x75
OP_DUP = 0x76
OP_EQUAL = 0x87
OP_EQUALVERIFY = 0x88
OP_PUSHDATA1 = 0x4c
OP_PUSHDATA2 = 0x4d
OP_PUSHDATA4 = 0x4e
OP_HASH160 = 0xa9
OP_CHECKSIG = 0xac
OP_CHECKMULTISIG = 0xae
OP_CHECKSEQUENCEVERIFY = 0xb2
def push_script_data(data_array: bytearray, data: bytes) -> None:
len_data: int = len(data)
if len_data == 0 or (len_data == 1 and data[0] == 0):
data_array += bytes((OP_0,))
return
if len_data == 1 and data[0] <= 16:
data_array += bytes((OP_1 - 1 + data[0],))
return
if len_data == 1 and data[0] == 0x81:
data_array += bytes((OP_1NEGATE,))
return
if len_data < OP_PUSHDATA1:
data_array += len_data.to_bytes(1, 'little')
elif len_data <= 0xff:
data_array += bytes((OP_PUSHDATA1, len_data))
elif len_data <= 0xffff:
data_array += bytes((OP_PUSHDATA2,)) + len_data.to_bytes(2, 'little')
else:
data_array += bytes((OP_PUSHDATA4,)) + len_data.to_bytes(4, 'little')
data_array += data

View File

@@ -1,50 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2024 tecnovert
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
import os
import select
import subprocess
def createDCRWallet(args, hex_seed, logging, delay_event):
logging.info('Creating DCR wallet')
(pipe_r, pipe_w) = os.pipe() # subprocess.PIPE is buffered, blocks when read
p = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=pipe_w, stderr=pipe_w)
try:
while p.poll() is None:
while len(select.select([pipe_r], [], [], 0)[0]) == 1:
buf = os.read(pipe_r, 1024).decode('utf-8')
logging.debug(f'dcrwallet {buf}')
response = None
if 'Use the existing configured private passphrase' in buf:
response = b'y\n'
elif 'Do you want to add an additional layer of encryption' in buf:
response = b'n\n'
elif 'Do you have an existing wallet seed' in buf:
response = b'y\n'
elif 'Enter existing wallet seed' in buf:
response = (hex_seed + '\n').encode('utf-8')
elif 'Seed input successful' in buf:
pass
elif 'Upgrading database from version' in buf:
pass
elif 'Ticket commitments db upgrade done' in buf:
pass
else:
raise ValueError(f'Unexpected output: {buf}')
if response is not None:
p.stdin.write(response)
p.stdin.flush()
delay_event.wait(0.1)
except Exception as e:
logging.error(f'dcrwallet --create failed: {e}')
finally:
if p.poll() is None:
p.terminate()
os.close(pipe_r)
os.close(pipe_w)
p.stdin.close()

View File

@@ -5,8 +5,8 @@
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php. # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
import hashlib
import random import random
import hashlib
from .btc import BTCInterface, find_vout_for_address_from_txobj from .btc import BTCInterface, find_vout_for_address_from_txobj
from basicswap.util import ( from basicswap.util import (
@@ -42,6 +42,9 @@ class FIROInterface(BTCInterface):
# No multiwallet support # No multiwallet support
self.rpc_wallet = make_rpc_func(self._rpcport, self._rpcauth, host=self._rpc_host) self.rpc_wallet = make_rpc_func(self._rpcport, self._rpcauth, host=self._rpc_host)
def checkWallets(self) -> int:
return 1
def getExchangeName(self, exchange_name): def getExchangeName(self, exchange_name):
return 'zcoin' return 'zcoin'
@@ -49,9 +52,6 @@ class FIROInterface(BTCInterface):
# load with -hdseed= parameter # load with -hdseed= parameter
pass pass
def checkWallets(self) -> int:
return 1
def getNewAddress(self, use_segwit, label='swap_receive'): def getNewAddress(self, use_segwit, label='swap_receive'):
return self.rpc('getnewaddress', [label]) return self.rpc('getnewaddress', [label])
# addr_plain = self.rpc('getnewaddress', [label]) # addr_plain = self.rpc('getnewaddress', [label])
@@ -76,7 +76,7 @@ class FIROInterface(BTCInterface):
return addr_info['ismine'] return addr_info['ismine']
return addr_info['ismine'] or addr_info['iswatchonly'] return addr_info['ismine'] or addr_info['iswatchonly']
def getSCLockScriptAddress(self, lock_script: bytes) -> str: def getSCLockScriptAddress(self, lock_script):
lock_tx_dest = self.getScriptDest(lock_script) lock_tx_dest = self.getScriptDest(lock_script)
address = self.encodeScriptDest(lock_tx_dest) address = self.encodeScriptDest(lock_tx_dest)
@@ -87,7 +87,7 @@ class FIROInterface(BTCInterface):
return address return address
def getLockTxHeight(self, txid, dest_address, bid_amount, rescan_from, find_index: bool = False, vout: int = -1): def getLockTxHeight(self, txid, dest_address, bid_amount, rescan_from, find_index: bool = False):
# Add watchonly address and rescan if required # Add watchonly address and rescan if required
if not self.isAddressMine(dest_address, or_watch_only=True): if not self.isAddressMine(dest_address, or_watch_only=True):
@@ -277,6 +277,8 @@ class FIROInterface(BTCInterface):
break break
utxos_hash = hasher.digest() utxos_hash = hasher.digest()
self._log.debug('sign_for_addr %s', sign_for_addr)
if self.using_segwit(): # TODO: Use isSegwitAddress when scantxoutset can use combo if self.using_segwit(): # TODO: Use isSegwitAddress when scantxoutset can use combo
# 'Address does not refer to key' for non p2pkh # 'Address does not refer to key' for non p2pkh
pkh = self.decodeAddress(sign_for_addr) pkh = self.decodeAddress(sign_for_addr)
@@ -337,7 +339,7 @@ class FIROInterface(BTCInterface):
return return
current_height -= 1 current_height -= 1
def getBlockWithTxns(self, block_hash: str): def getBlockWithTxns(self, block_hash):
# TODO: Bypass decoderawtransaction and getblockheader # TODO: Bypass decoderawtransaction and getblockheader
block = self.rpc('getblock', [block_hash, False]) block = self.rpc('getblock', [block_hash, False])
block_header = self.rpc('getblockheader', [block_hash]) block_header = self.rpc('getblockheader', [block_hash])
@@ -355,11 +357,9 @@ class FIROInterface(BTCInterface):
block_rv = { block_rv = {
'hash': block_hash, 'hash': block_hash,
'previousblockhash': block_header['previousblockhash'],
'tx': tx_rv, 'tx': tx_rv,
'confirmations': block_header['confirmations'], 'confirmations': block_header['confirmations'],
'height': block_header['height'], 'height': block_header['height'],
'time': block_header['time'],
'version': block_header['version'], 'version': block_header['version'],
'merkleroot': block_header['merkleroot'], 'merkleroot': block_header['merkleroot'],
} }

View File

@@ -32,16 +32,6 @@ class LTCInterface(BTCInterface):
return self.rpc_wallet_mweb('sendtoaddress', params) return self.rpc_wallet_mweb('sendtoaddress', params)
return self.rpc_wallet('sendtoaddress', params) return self.rpc_wallet('sendtoaddress', params)
def createUTXO(self, value_sats: int):
# Create a new address and send value_sats to it
spendable_balance = self.getSpendableBalance()
if spendable_balance < value_sats:
raise ValueError('Balance too low')
address = self.getNewAddress(self._use_segwit, 'create_utxo')
return self.withdrawCoin(self.format_amount(value_sats), 'plain', address, False), address
def getWalletInfo(self): def getWalletInfo(self):
rv = super(LTCInterface, self).getWalletInfo() rv = super(LTCInterface, self).getWalletInfo()
@@ -49,32 +39,14 @@ class LTCInterface(BTCInterface):
rv['mweb_balance'] = mweb_info['balance'] rv['mweb_balance'] = mweb_info['balance']
rv['mweb_unconfirmed'] = mweb_info['unconfirmed_balance'] rv['mweb_unconfirmed'] = mweb_info['unconfirmed_balance']
rv['mweb_immature'] = mweb_info['immature_balance'] rv['mweb_immature'] = mweb_info['immature_balance']
return rv
def getUnspentsByAddr(self): # Add unconfirmed mweb -> plain txns to the unconfirmed_balance
unspent_addr = dict() txns = self.rpc_wallet('listtransactions')
unspent = self.rpc_wallet('listunspent') for tx in reversed(txns):
for u in unspent: amount: float = tx.get('amount', 0.0)
if u.get('spendable', False) is False: if tx['confirmations'] == 0 and tx.get('mweb_out', None) and amount > 0.0:
continue rv['unconfirmed_balance'] += amount
if u.get('solvable', False) is False: # Filter out mweb outputs return rv
continue
if 'address' not in u:
continue
if 'desc' in u:
desc = u['desc']
if self.using_segwit:
if self.use_p2shp2wsh():
if not desc.startswith('sh(wpkh'):
continue
else:
if not desc.startswith('wpkh'):
continue
else:
if not desc.startswith('pkh'):
continue
unspent_addr[u['address']] = unspent_addr.get(u['address'], 0) + self.make_int(u['amount'], r=1)
return unspent_addr
class LTCInterfaceMWEB(LTCInterface): class LTCInterfaceMWEB(LTCInterface):

View File

@@ -13,12 +13,7 @@ from coincurve.keys import (
PublicKey, PublicKey,
PrivateKey, PrivateKey,
) )
from basicswap.interface.btc import ( from .btc import BTCInterface, find_vout_for_address_from_txobj, findOutput
BTCInterface,
extractScriptLockRefundScriptValues,
findOutput,
find_vout_for_address_from_txobj,
)
from basicswap.rpc import make_rpc_func from basicswap.rpc import make_rpc_func
from basicswap.chainparams import Coins from basicswap.chainparams import Coins
from basicswap.interface.contrib.nav_test_framework.mininode import ( from basicswap.interface.contrib.nav_test_framework.mininode import (
@@ -29,6 +24,7 @@ from basicswap.interface.contrib.nav_test_framework.mininode import (
CTransaction, CTransaction,
CTxInWitness, CTxInWitness,
FromHex, FromHex,
uint256_from_str,
) )
from basicswap.util.crypto import hash160 from basicswap.util.crypto import hash160
from basicswap.util.address import ( from basicswap.util.address import (
@@ -37,7 +33,7 @@ from basicswap.util.address import (
encodeAddress, encodeAddress,
) )
from basicswap.util import ( from basicswap.util import (
b2i, i2b, i2h, i2b, i2h,
ensure, ensure,
) )
from basicswap.basicswap_util import ( from basicswap.basicswap_util import (
@@ -73,20 +69,20 @@ class NAVInterface(BTCInterface):
# No multiwallet support # No multiwallet support
self.rpc_wallet = make_rpc_func(self._rpcport, self._rpcauth, host=self._rpc_host) self.rpc_wallet = make_rpc_func(self._rpcport, self._rpcauth, host=self._rpc_host)
def checkWallets(self) -> int:
return 1
def use_p2shp2wsh(self) -> bool: def use_p2shp2wsh(self) -> bool:
# p2sh-p2wsh # p2sh-p2wsh
return True return True
def seedToMnemonic(self, key: bytes) -> None: def seedToMnemonic(self, key):
return Mnemonic('english').to_mnemonic(key) return Mnemonic('english').to_mnemonic(key)
def initialiseWallet(self, key): def initialiseWallet(self, key):
# Load with -importmnemonic= parameter # load with -importmnemonic= parameter
pass pass
def checkWallets(self) -> int:
return 1
def getWalletSeedID(self): def getWalletSeedID(self):
return self.rpc('getwalletinfo')['hdmasterkeyid'] return self.rpc('getwalletinfo')['hdmasterkeyid']
@@ -220,6 +216,8 @@ class NAVInterface(BTCInterface):
break break
utxos_hash = hasher.digest() utxos_hash = hasher.digest()
self._log.debug('sign_for_addr %s', sign_for_addr)
if self.using_segwit(): # TODO: Use isSegwitAddress when scantxoutset can use combo if self.using_segwit(): # TODO: Use isSegwitAddress when scantxoutset can use combo
# 'Address does not refer to key' for non p2pkh # 'Address does not refer to key' for non p2pkh
addr_info = self.rpc('validateaddress', [addr, ]) addr_info = self.rpc('validateaddress', [addr, ])
@@ -309,7 +307,7 @@ class NAVInterface(BTCInterface):
def createRedeemTxn(self, prevout, output_addr: str, output_value: int, txn_script: bytes) -> str: def createRedeemTxn(self, prevout, output_addr: str, output_value: int, txn_script: bytes) -> str:
tx = CTransaction() tx = CTransaction()
tx.nVersion = self.txVersion() tx.nVersion = self.txVersion()
prev_txid = b2i(bytes.fromhex(prevout['txid'])) prev_txid = uint256_from_str(bytes.fromhex(prevout['txid'])[::-1])
tx.vin.append(CTxIn(COutPoint(prev_txid, prevout['vout']), tx.vin.append(CTxIn(COutPoint(prev_txid, prevout['vout']),
scriptSig=self.getScriptScriptSig(txn_script))) scriptSig=self.getScriptScriptSig(txn_script)))
@@ -323,7 +321,7 @@ class NAVInterface(BTCInterface):
tx = CTransaction() tx = CTransaction()
tx.nVersion = self.txVersion() tx.nVersion = self.txVersion()
tx.nLockTime = locktime tx.nLockTime = locktime
prev_txid = b2i(bytes.fromhex(prevout['txid'])) prev_txid = uint256_from_str(bytes.fromhex(prevout['txid'])[::-1])
tx.vin.append(CTxIn(COutPoint(prev_txid, prevout['vout']), tx.vin.append(CTxIn(COutPoint(prev_txid, prevout['vout']),
nSequence=sequence, nSequence=sequence,
scriptSig=self.getScriptScriptSig(txn_script))) scriptSig=self.getScriptScriptSig(txn_script)))
@@ -419,7 +417,7 @@ class NAVInterface(BTCInterface):
return return
current_height -= 1 current_height -= 1
def getLockTxHeight(self, txid, dest_address, bid_amount, rescan_from, find_index: bool = False, vout: int = -1): def getLockTxHeight(self, txid, dest_address, bid_amount, rescan_from, find_index: bool = False):
# Add watchonly address and rescan if required # Add watchonly address and rescan if required
if not self.isAddressMine(dest_address, or_watch_only=True): if not self.isAddressMine(dest_address, or_watch_only=True):
@@ -483,18 +481,16 @@ class NAVInterface(BTCInterface):
block_rv = { block_rv = {
'hash': block_hash, 'hash': block_hash,
'previousblockhash': block_header['previousblockhash'],
'tx': tx_rv, 'tx': tx_rv,
'confirmations': block_header['confirmations'], 'confirmations': block_header['confirmations'],
'height': block_header['height'], 'height': block_header['height'],
'time': block_header['time'],
'version': block_header['version'], 'version': block_header['version'],
'merkleroot': block_header['merkleroot'], 'merkleroot': block_header['merkleroot'],
} }
return block_rv return block_rv
def getScriptScriptSig(self, script: bytes) -> bytes: def getScriptScriptSig(self, script: bytes) -> bytearray:
return self.getP2SHP2WSHScriptSig(script) return self.getP2SHP2WSHScriptSig(script)
def getScriptDest(self, script): def getScriptDest(self, script):
@@ -516,7 +512,7 @@ class NAVInterface(BTCInterface):
tx.vout.append(self.txoType()(output_amount, script_pk)) tx.vout.append(self.txoType()(output_amount, script_pk))
return tx.serialize() return tx.serialize()
def spendBLockTx(self, chain_b_lock_txid: bytes, address_to: str, kbv: bytes, kbs: bytes, cb_swap_value: int, b_fee: int, restore_height: int, lock_tx_vout=None) -> bytes: def spendBLockTx(self, chain_b_lock_txid: bytes, address_to: str, kbv: bytes, kbs: bytes, cb_swap_value: int, b_fee: int, restore_height: int) -> bytes:
self._log.info('spendBLockTx %s:\n', chain_b_lock_txid.hex()) self._log.info('spendBLockTx %s:\n', chain_b_lock_txid.hex())
wtx = self.rpc('gettransaction', [chain_b_lock_txid.hex(), ]) wtx = self.rpc('gettransaction', [chain_b_lock_txid.hex(), ])
lock_tx = self.loadTx(bytes.fromhex(wtx['hex'])) lock_tx = self.loadTx(bytes.fromhex(wtx['hex']))
@@ -530,7 +526,7 @@ class NAVInterface(BTCInterface):
tx = CTransaction() tx = CTransaction()
tx.nVersion = self.txVersion() tx.nVersion = self.txVersion()
chain_b_lock_txid_int = b2i(chain_b_lock_txid) chain_b_lock_txid_int = uint256_from_str(chain_b_lock_txid[::-1])
script_sig = self.getInputScriptForPubkeyHash(self.getPubkeyHash(Kbs)) script_sig = self.getInputScriptForPubkeyHash(self.getPubkeyHash(Kbs))
@@ -682,7 +678,7 @@ class NAVInterface(BTCInterface):
ensure(locked_n is not None, 'Output not found in tx') ensure(locked_n is not None, 'Output not found in tx')
locked_coin = tx_lock_refund.vout[locked_n].nValue locked_coin = tx_lock_refund.vout[locked_n].nValue
A, B, lock2_value, C = extractScriptLockRefundScriptValues(script_lock_refund) A, B, lock2_value, C = self.extractScriptLockRefundScriptValues(script_lock_refund)
tx_lock_refund.rehash() tx_lock_refund.rehash()
tx_lock_refund_hash_int = tx_lock_refund.sha256 tx_lock_refund_hash_int = tx_lock_refund.sha256

View File

@@ -7,6 +7,9 @@
from .btc import BTCInterface from .btc import BTCInterface
from basicswap.chainparams import Coins from basicswap.chainparams import Coins
from basicswap.util import (
make_int,
)
class NMCInterface(BTCInterface): class NMCInterface(BTCInterface):
@@ -14,7 +17,7 @@ class NMCInterface(BTCInterface):
def coin_type(): def coin_type():
return Coins.NMC return Coins.NMC
def getLockTxHeight(self, txid, dest_address, bid_amount, rescan_from, find_index: bool = False, vout: int = -1): def getLockTxHeight(self, txid, dest_address, bid_amount, rescan_from, find_index=False):
self._log.debug('[rm] scantxoutset start') # scantxoutset is slow self._log.debug('[rm] scantxoutset start') # scantxoutset is slow
ro = self.rpc('scantxoutset', ['start', ['addr({})'.format(dest_address)]]) # TODO: Use combo(address) where possible ro = self.rpc('scantxoutset', ['start', ['addr({})'.format(dest_address)]]) # TODO: Use combo(address) where possible
self._log.debug('[rm] scantxoutset end') self._log.debug('[rm] scantxoutset end')
@@ -23,7 +26,7 @@ class NMCInterface(BTCInterface):
if txid and o['txid'] != txid.hex(): if txid and o['txid'] != txid.hex():
continue continue
# Verify amount # Verify amount
if self.make_int(o['amount']) != int(bid_amount): if make_int(o['amount']) != int(bid_amount):
self._log.warning('Found output to lock tx address of incorrect value: %s, %s', str(o['amount']), o['txid']) self._log.warning('Found output to lock tx address of incorrect value: %s, %s', str(o['amount']), o['txid'])
continue continue

View File

@@ -14,10 +14,11 @@ from basicswap.contrib.test_framework.messages import (
from basicswap.contrib.test_framework.script import ( from basicswap.contrib.test_framework.script import (
CScript, CScript,
OP_0, OP_0,
OP_DUP, OP_HASH160, OP_EQUALVERIFY, OP_CHECKSIG, OP_DUP, OP_HASH160, OP_EQUALVERIFY, OP_CHECKSIG
) )
from basicswap.util import ( from basicswap.util import (
ensure, ensure,
make_int,
TemporaryError, TemporaryError,
) )
from basicswap.util.script import ( from basicswap.util.script import (
@@ -26,15 +27,10 @@ from basicswap.util.script import (
getWitnessElementLen, getWitnessElementLen,
) )
from basicswap.util.address import ( from basicswap.util.address import (
encodeStealthAddress, toWIF,
) encodeStealthAddress)
from basicswap.interface.btc import (
BTCInterface,
extractScriptLockScriptValues,
extractScriptLockRefundScriptValues,
)
from basicswap.chainparams import Coins, chainparams from basicswap.chainparams import Coins, chainparams
from .btc import BTCInterface
class BalanceTypes(IntEnum): class BalanceTypes(IntEnum):
@@ -78,9 +74,6 @@ class PARTInterface(BTCInterface):
super().__init__(coin_settings, network, swap_client) super().__init__(coin_settings, network, swap_client)
self.setAnonTxRingSize(int(coin_settings.get('anon_tx_ring_size', 12))) self.setAnonTxRingSize(int(coin_settings.get('anon_tx_ring_size', 12)))
def use_tx_vsize(self) -> bool:
return True
def setAnonTxRingSize(self, value): def setAnonTxRingSize(self, value):
ensure(value >= 3 and value < 33, 'Invalid anon_tx_ring_size value') ensure(value >= 3 and value < 33, 'Invalid anon_tx_ring_size value')
self._anon_tx_ring_size = value self._anon_tx_ring_size = value
@@ -100,7 +93,7 @@ class PARTInterface(BTCInterface):
index_info = self.rpc('getinsightinfo' if int(str(version)[:2]) > 19 else 'getindexinfo') index_info = self.rpc('getinsightinfo' if int(str(version)[:2]) > 19 else 'getindexinfo')
return index_info['spentindex'] return index_info['spentindex']
def initialiseWallet(self, key: bytes) -> None: def initialiseWallet(self, key):
raise ValueError('TODO') raise ValueError('TODO')
def withdrawCoin(self, value, addr_to, subfee): def withdrawCoin(self, value, addr_to, subfee):
@@ -352,21 +345,21 @@ class PARTInterfaceBlind(PARTInterface):
ensure(lock_output_n is not None, 'Output not found in tx') ensure(lock_output_n is not None, 'Output not found in tx')
# Check value # Check value
locked_txo_value = self.make_int(blinded_info['amount']) locked_txo_value = make_int(blinded_info['amount'])
ensure(locked_txo_value == swap_value, 'Bad locked value') ensure(locked_txo_value == swap_value, 'Bad locked value')
# Check script # Check script
lock_txo_scriptpk = bytes.fromhex(lock_tx_obj['vout'][lock_output_n]['scriptPubKey']['hex']) lock_txo_scriptpk = bytes.fromhex(lock_tx_obj['vout'][lock_output_n]['scriptPubKey']['hex'])
script_pk = CScript([OP_0, hashlib.sha256(script_out).digest()]) script_pk = CScript([OP_0, hashlib.sha256(script_out).digest()])
ensure(lock_txo_scriptpk == script_pk, 'Bad output script') ensure(lock_txo_scriptpk == script_pk, 'Bad output script')
A, B = extractScriptLockScriptValues(script_out) A, B = self.extractScriptLockScriptValues(script_out)
ensure(A == Kal, 'Bad script leader pubkey') ensure(A == Kal, 'Bad script leader pubkey')
ensure(B == Kaf, 'Bad script follower pubkey') ensure(B == Kaf, 'Bad script follower pubkey')
# TODO: Check that inputs are unspent, rangeproofs and commitments sum # TODO: Check that inputs are unspent, rangeproofs and commitments sum
# Verify fee rate # Verify fee rate
vsize = lock_tx_obj['vsize'] vsize = lock_tx_obj['vsize']
fee_paid = self.make_int(lock_tx_obj['vout'][0]['ct_fee']) fee_paid = make_int(lock_tx_obj['vout'][0]['ct_fee'])
fee_rate_paid = fee_paid * 1000 // vsize fee_rate_paid = fee_paid * 1000 // vsize
@@ -401,13 +394,13 @@ class PARTInterfaceBlind(PARTInterface):
lock_refund_output_n, blinded_info = self.findOutputByNonce(lock_refund_tx_obj, nonce) lock_refund_output_n, blinded_info = self.findOutputByNonce(lock_refund_tx_obj, nonce)
ensure(lock_refund_output_n is not None, 'Output not found in tx') ensure(lock_refund_output_n is not None, 'Output not found in tx')
lock_refund_txo_value = self.make_int(blinded_info['amount']) lock_refund_txo_value = make_int(blinded_info['amount'])
# Check script # Check script
lock_refund_txo_scriptpk = bytes.fromhex(lock_refund_tx_obj['vout'][lock_refund_output_n]['scriptPubKey']['hex']) lock_refund_txo_scriptpk = bytes.fromhex(lock_refund_tx_obj['vout'][lock_refund_output_n]['scriptPubKey']['hex'])
script_pk = CScript([OP_0, hashlib.sha256(script_out).digest()]) script_pk = CScript([OP_0, hashlib.sha256(script_out).digest()])
ensure(lock_refund_txo_scriptpk == script_pk, 'Bad output script') ensure(lock_refund_txo_scriptpk == script_pk, 'Bad output script')
A, B, csv_val, C = extractScriptLockRefundScriptValues(script_out) A, B, csv_val, C = self.extractScriptLockRefundScriptValues(script_out)
ensure(A == Kal, 'Bad script pubkey') ensure(A == Kal, 'Bad script pubkey')
ensure(B == Kaf, 'Bad script pubkey') ensure(B == Kaf, 'Bad script pubkey')
ensure(csv_val == csv_val_expect, 'Bad script csv value') ensure(csv_val == csv_val_expect, 'Bad script csv value')
@@ -422,7 +415,7 @@ class PARTInterfaceBlind(PARTInterface):
ensure(rv['inputs_valid'] is True, 'Invalid inputs') ensure(rv['inputs_valid'] is True, 'Invalid inputs')
# Check value # Check value
fee_paid = self.make_int(lock_refund_tx_obj['vout'][0]['ct_fee']) fee_paid = make_int(lock_refund_tx_obj['vout'][0]['ct_fee'])
ensure(swap_value - lock_refund_txo_value == fee_paid, 'Bad output value') ensure(swap_value - lock_refund_txo_value == fee_paid, 'Bad output value')
# Check fee rate # Check fee rate
@@ -470,7 +463,7 @@ class PARTInterfaceBlind(PARTInterface):
dummy_witness_stack = self.getScriptLockRefundSpendTxDummyWitness(prevout_script) dummy_witness_stack = self.getScriptLockRefundSpendTxDummyWitness(prevout_script)
witness_bytes = self.getWitnessStackSerialisedLength(dummy_witness_stack) witness_bytes = self.getWitnessStackSerialisedLength(dummy_witness_stack)
vsize = self.getTxVSize(self.loadTx(tx_bytes), add_witness_bytes=witness_bytes) vsize = self.getTxVSize(self.loadTx(tx_bytes), add_witness_bytes=witness_bytes)
fee_paid = self.make_int(lock_refund_spend_tx_obj['vout'][0]['ct_fee']) fee_paid = make_int(lock_refund_spend_tx_obj['vout'][0]['ct_fee'])
fee_rate_paid = fee_paid * 1000 // vsize fee_rate_paid = fee_paid * 1000 // vsize
ensure(self.compareFeeRates(fee_rate_paid, feerate), 'Bad fee rate, expected: {}'.format(feerate)) ensure(self.compareFeeRates(fee_rate_paid, feerate), 'Bad fee rate, expected: {}'.format(feerate))
@@ -534,7 +527,7 @@ class PARTInterfaceBlind(PARTInterface):
rv = self.rpc_wallet('fundrawtransactionfrom', ['blind', lock_spend_tx_hex, inputs_info, outputs_info, options]) rv = self.rpc_wallet('fundrawtransactionfrom', ['blind', lock_spend_tx_hex, inputs_info, outputs_info, options])
lock_spend_tx_hex = rv['hex'] lock_spend_tx_hex = rv['hex']
lock_spend_tx_obj = self.rpc('decoderawtransaction', [lock_spend_tx_hex]) lock_spend_tx_obj = self.rpc('decoderawtransaction', [lock_spend_tx_hex])
pay_fee = self.make_int(lock_spend_tx_obj['vout'][0]['ct_fee']) pay_fee = make_int(lock_spend_tx_obj['vout'][0]['ct_fee'])
# lock_spend_tx_hex does not include the dummy witness stack # lock_spend_tx_hex does not include the dummy witness stack
witness_bytes = self.getWitnessStackSerialisedLength(dummy_witness_stack) witness_bytes = self.getWitnessStackSerialisedLength(dummy_witness_stack)
@@ -606,8 +599,8 @@ class PARTInterfaceBlind(PARTInterface):
ensure(rv['inputs_valid'] is True, 'Invalid inputs') ensure(rv['inputs_valid'] is True, 'Invalid inputs')
# Check amount # Check amount
fee_paid = self.make_int(lock_spend_tx_obj['vout'][0]['ct_fee']) fee_paid = make_int(lock_spend_tx_obj['vout'][0]['ct_fee'])
amount_difference = self.make_int(input_blinded_info['amount']) - self.make_int(output_blinded_info['amount']) amount_difference = make_int(input_blinded_info['amount']) - make_int(output_blinded_info['amount'])
ensure(fee_paid == amount_difference, 'Invalid output amount') ensure(fee_paid == amount_difference, 'Invalid output amount')
# Check fee # Check fee
@@ -637,7 +630,7 @@ class PARTInterfaceBlind(PARTInterface):
addr_info = self.rpc_wallet('getaddressinfo', [addr_out]) addr_info = self.rpc_wallet('getaddressinfo', [addr_out])
output_pubkey_hex = addr_info['pubkey'] output_pubkey_hex = addr_info['pubkey']
A, B, lock2_value, C = extractScriptLockRefundScriptValues(script_lock_refund) A, B, lock2_value, C = self.extractScriptLockRefundScriptValues(script_lock_refund)
# Follower won't be able to decode output to check amount, shouldn't matter as fee is public and output is to leader, sum has to balance # Follower won't be able to decode output to check amount, shouldn't matter as fee is public and output is to leader, sum has to balance
@@ -671,7 +664,7 @@ class PARTInterfaceBlind(PARTInterface):
def getSpendableBalance(self) -> int: def getSpendableBalance(self) -> int:
return self.make_int(self.rpc_wallet('getbalances')['mine']['blind_trusted']) return self.make_int(self.rpc_wallet('getbalances')['mine']['blind_trusted'])
def publishBLockTx(self, vkbv: bytes, Kbs: bytes, output_amount: int, feerate: int, unlock_time: int = 0) -> bytes: def publishBLockTx(self, vkbv: bytes, Kbs: bytes, output_amount: int, feerate: int, delay_for: int = 10, unlock_time: int = 0) -> bytes:
Kbv = self.getPubkey(vkbv) Kbv = self.getPubkey(vkbv)
sx_addr = self.formatStealthAddress(Kbv, Kbs) sx_addr = self.formatStealthAddress(Kbv, Kbs)
self._log.debug('sx_addr: {}'.format(sx_addr)) self._log.debug('sx_addr: {}'.format(sx_addr))
@@ -695,7 +688,8 @@ class PARTInterfaceBlind(PARTInterface):
else: else:
addr_info = self.rpc_wallet('getaddressinfo', [sx_addr]) addr_info = self.rpc_wallet('getaddressinfo', [sx_addr])
if not addr_info['iswatchonly']: if not addr_info['iswatchonly']:
wif_scan_key = self.encodeKey(kbv) wif_prefix = self.chainparams_network()['key_prefix']
wif_scan_key = toWIF(wif_prefix, kbv)
self.rpc_wallet('importstealthaddress', [wif_scan_key, Kbs.hex()]) self.rpc_wallet('importstealthaddress', [wif_scan_key, Kbs.hex()])
self._log.info('Imported watch-only sx_addr: {}'.format(sx_addr)) self._log.info('Imported watch-only sx_addr: {}'.format(sx_addr))
self._log.info('Rescanning {} chain from height: {}'.format(self.coin_name(), restore_height)) self._log.info('Rescanning {} chain from height: {}'.format(self.coin_name(), restore_height))
@@ -709,7 +703,7 @@ class PARTInterfaceBlind(PARTInterface):
assert (tx['outputs'][0]['stealth_address'] == sx_addr) # Should not be possible assert (tx['outputs'][0]['stealth_address'] == sx_addr) # Should not be possible
ensure(tx['outputs'][0]['type'] == 'blind', 'Output is not anon') ensure(tx['outputs'][0]['type'] == 'blind', 'Output is not anon')
if self.make_int(tx['outputs'][0]['amount']) == cb_swap_value: if make_int(tx['outputs'][0]['amount']) == cb_swap_value:
height = 0 height = 0
if tx['confirmations'] > 0: if tx['confirmations'] > 0:
chain_height = self.rpc('getblockcount') chain_height = self.rpc('getblockcount')
@@ -720,14 +714,15 @@ class PARTInterfaceBlind(PARTInterface):
return -1 return -1
return None return None
def spendBLockTx(self, chain_b_lock_txid: bytes, address_to: str, kbv: bytes, kbs: bytes, cb_swap_value: int, b_fee: int, restore_height: int, spend_actual_balance: bool = False, lock_tx_vout=None) -> bytes: def spendBLockTx(self, chain_b_lock_txid: bytes, address_to: str, kbv: bytes, kbs: bytes, cb_swap_value: int, b_fee: int, restore_height: int, spend_actual_balance: bool = False) -> bytes:
Kbv = self.getPubkey(kbv) Kbv = self.getPubkey(kbv)
Kbs = self.getPubkey(kbs) Kbs = self.getPubkey(kbs)
sx_addr = self.formatStealthAddress(Kbv, Kbs) sx_addr = self.formatStealthAddress(Kbv, Kbs)
addr_info = self.rpc_wallet('getaddressinfo', [sx_addr]) addr_info = self.rpc_wallet('getaddressinfo', [sx_addr])
if not addr_info['ismine']: if not addr_info['ismine']:
wif_scan_key = self.encodeKey(kbv) wif_prefix = self.chainparams_network()['key_prefix']
wif_spend_key = self.encodeKey(kbs) wif_scan_key = toWIF(wif_prefix, kbv)
wif_spend_key = toWIF(wif_prefix, kbs)
self.rpc_wallet('importstealthaddress', [wif_scan_key, wif_spend_key]) self.rpc_wallet('importstealthaddress', [wif_scan_key, wif_spend_key])
self._log.info('Imported spend key for sx_addr: {}'.format(sx_addr)) self._log.info('Imported spend key for sx_addr: {}'.format(sx_addr))
self._log.info('Rescanning {} chain from height: {}'.format(self.coin_name(), restore_height)) self._log.info('Rescanning {} chain from height: {}'.format(self.coin_name(), restore_height))
@@ -746,7 +741,7 @@ class PARTInterfaceBlind(PARTInterface):
raise ValueError('Too many spendable outputs') raise ValueError('Too many spendable outputs')
utxo = utxos[0] utxo = utxos[0]
utxo_sats = self.make_int(utxo['amount']) utxo_sats = make_int(utxo['amount'])
if spend_actual_balance and utxo_sats != cb_swap_value: if spend_actual_balance and utxo_sats != cb_swap_value:
self._log.warning('Spending actual balance {}, not swap value {}.'.format(utxo_sats, cb_swap_value)) self._log.warning('Spending actual balance {}, not swap value {}.'.format(utxo_sats, cb_swap_value))
@@ -807,7 +802,7 @@ class PARTInterfaceAnon(PARTInterface):
def coin_name(self) -> str: def coin_name(self) -> str:
return super().coin_name() + ' Anon' return super().coin_name() + ' Anon'
def publishBLockTx(self, kbv: bytes, Kbs: bytes, output_amount: int, feerate: int, unlock_time: int = 0) -> bytes: def publishBLockTx(self, kbv: bytes, Kbs: bytes, output_amount: int, feerate: int, delay_for: int = 10, unlock_time: int = 0) -> bytes:
Kbv = self.getPubkey(kbv) Kbv = self.getPubkey(kbv)
sx_addr = self.formatStealthAddress(Kbv, Kbs) sx_addr = self.formatStealthAddress(Kbv, Kbs)
@@ -831,7 +826,8 @@ class PARTInterfaceAnon(PARTInterface):
else: else:
addr_info = self.rpc_wallet('getaddressinfo', [sx_addr]) addr_info = self.rpc_wallet('getaddressinfo', [sx_addr])
if not addr_info['iswatchonly']: if not addr_info['iswatchonly']:
wif_scan_key = self.encodeKey(kbv) wif_prefix = self.chainparams_network()['key_prefix']
wif_scan_key = toWIF(wif_prefix, kbv)
self.rpc_wallet('importstealthaddress', [wif_scan_key, Kbs.hex()]) self.rpc_wallet('importstealthaddress', [wif_scan_key, Kbs.hex()])
self._log.info('Imported watch-only sx_addr: {}'.format(sx_addr)) self._log.info('Imported watch-only sx_addr: {}'.format(sx_addr))
self._log.info('Rescanning {} chain from height: {}'.format(self.coin_name(), restore_height)) self._log.info('Rescanning {} chain from height: {}'.format(self.coin_name(), restore_height))
@@ -845,7 +841,7 @@ class PARTInterfaceAnon(PARTInterface):
assert (tx['outputs'][0]['stealth_address'] == sx_addr) # Should not be possible assert (tx['outputs'][0]['stealth_address'] == sx_addr) # Should not be possible
ensure(tx['outputs'][0]['type'] == 'anon', 'Output is not anon') ensure(tx['outputs'][0]['type'] == 'anon', 'Output is not anon')
if self.make_int(tx['outputs'][0]['amount']) == cb_swap_value: if make_int(tx['outputs'][0]['amount']) == cb_swap_value:
height = 0 height = 0
if tx['confirmations'] > 0: if tx['confirmations'] > 0:
chain_height = self.rpc('getblockcount') chain_height = self.rpc('getblockcount')
@@ -856,14 +852,15 @@ class PARTInterfaceAnon(PARTInterface):
return -1 return -1
return None return None
def spendBLockTx(self, chain_b_lock_txid: bytes, address_to: str, kbv: bytes, kbs: bytes, cb_swap_value: int, b_fee: int, restore_height: int, spend_actual_balance: bool = False, lock_tx_vout=None) -> bytes: def spendBLockTx(self, chain_b_lock_txid: bytes, address_to: str, kbv: bytes, kbs: bytes, cb_swap_value: int, b_fee: int, restore_height: int, spend_actual_balance: bool = False) -> bytes:
Kbv = self.getPubkey(kbv) Kbv = self.getPubkey(kbv)
Kbs = self.getPubkey(kbs) Kbs = self.getPubkey(kbs)
sx_addr = self.formatStealthAddress(Kbv, Kbs) sx_addr = self.formatStealthAddress(Kbv, Kbs)
addr_info = self.rpc_wallet('getaddressinfo', [sx_addr]) addr_info = self.rpc_wallet('getaddressinfo', [sx_addr])
if not addr_info['ismine']: if not addr_info['ismine']:
wif_scan_key = self.encodeKey(kbv) wif_prefix = self.chainparams_network()['key_prefix']
wif_spend_key = self.encodeKey(kbs) wif_scan_key = toWIF(wif_prefix, kbv)
wif_spend_key = toWIF(wif_prefix, kbs)
self.rpc_wallet('importstealthaddress', [wif_scan_key, wif_spend_key]) self.rpc_wallet('importstealthaddress', [wif_scan_key, wif_spend_key])
self._log.info('Imported spend key for sx_addr: {}'.format(sx_addr)) self._log.info('Imported spend key for sx_addr: {}'.format(sx_addr))
self._log.info('Rescanning {} chain from height: {}'.format(self.coin_name(), restore_height)) self._log.info('Rescanning {} chain from height: {}'.format(self.coin_name(), restore_height))
@@ -877,7 +874,7 @@ class PARTInterfaceAnon(PARTInterface):
raise ValueError('Too many spendable outputs') raise ValueError('Too many spendable outputs')
utxo = autxos[0] utxo = autxos[0]
utxo_sats = self.make_int(utxo['amount']) utxo_sats = make_int(utxo['amount'])
if spend_actual_balance and utxo_sats != cb_swap_value: if spend_actual_balance and utxo_sats != cb_swap_value:
self._log.warning('Spending actual balance {}, not swap value {}.'.format(utxo_sats, cb_swap_value)) self._log.warning('Spending actual balance {}, not swap value {}.'.format(utxo_sats, cb_swap_value))

View File

@@ -75,11 +75,9 @@ class PIVXInterface(BTCInterface):
block_rv = { block_rv = {
'hash': block_hash, 'hash': block_hash,
'previousblockhash': block_header['previousblockhash'],
'tx': tx_rv, 'tx': tx_rv,
'confirmations': block_header['confirmations'], 'confirmations': block_header['confirmations'],
'height': block_header['height'], 'height': block_header['height'],
'time': block_header['time'],
'version': block_header['version'], 'version': block_header['version'],
'merkleroot': block_header['merkleroot'], 'merkleroot': block_header['merkleroot'],
} }

View File

@@ -24,21 +24,20 @@ from coincurve.dleag import (
verify_ed25519_point, verify_ed25519_point,
) )
from basicswap.interface.base import ( from basicswap.interface import (
Curves, Curves)
)
from basicswap.util import ( from basicswap.util import (
i2b, b2i, b2h, i2b, b2i, b2h,
dumpj, dumpj,
ensure, ensure,
make_int,
TemporaryError) TemporaryError)
from basicswap.util.network import ( from basicswap.util.network import (
is_private_ip_address) is_private_ip_address)
from basicswap.rpc_xmr import ( from basicswap.rpc_xmr import (
make_xmr_rpc_func, make_xmr_rpc_func,
make_xmr_rpc2_func) make_xmr_rpc2_func)
from basicswap.chainparams import XMR_COIN, Coins from basicswap.chainparams import XMR_COIN, CoinInterface, Coins
from basicswap.interface.base import CoinInterface
class XMRInterface(CoinInterface): class XMRInterface(CoinInterface):
@@ -77,13 +76,11 @@ class XMRInterface(CoinInterface):
@staticmethod @staticmethod
def xmr_swap_b_lock_spend_tx_vsize() -> int: def xmr_swap_b_lock_spend_tx_vsize() -> int:
# TODO: Estimate with ringsize # TODO: Estimate with ringsize
return 1604 return 1507
def __init__(self, coin_settings, network, swap_client=None): def __init__(self, coin_settings, network, swap_client=None):
super().__init__(network) super().__init__(network)
self._addr_prefix = self.chainparams_network()['address_prefix']
self.blocks_confirmed = coin_settings['blocks_confirmed'] self.blocks_confirmed = coin_settings['blocks_confirmed']
self._restore_height = coin_settings.get('restore_height', 0) self._restore_height = coin_settings.get('restore_height', 0)
self.setFeePriority(coin_settings.get('fee_priority', 0)) self.setFeePriority(coin_settings.get('fee_priority', 0))
@@ -129,6 +126,9 @@ class XMRInterface(CoinInterface):
self.rpc2 = make_xmr_rpc2_func(coin_settings['rpcport'], daemon_login, host=rpchost, proxy_host=proxy_host, proxy_port=proxy_port, default_timeout=self._rpctimeout, tag='Node ') # non-json endpoint self.rpc2 = make_xmr_rpc2_func(coin_settings['rpcport'], daemon_login, host=rpchost, proxy_host=proxy_host, proxy_port=proxy_port, default_timeout=self._rpctimeout, tag='Node ') # non-json endpoint
self.rpc_wallet = make_xmr_rpc_func(coin_settings['walletrpcport'], coin_settings['walletrpcauth'], host=coin_settings.get('walletrpchost', '127.0.0.1'), default_timeout=self._walletrpctimeout, tag='Wallet ') self.rpc_wallet = make_xmr_rpc_func(coin_settings['walletrpcport'], coin_settings['walletrpcauth'], host=coin_settings.get('walletrpchost', '127.0.0.1'), default_timeout=self._walletrpctimeout, tag='Wallet ')
def checkWallets(self) -> int:
return 1
def setFeePriority(self, new_priority): def setFeePriority(self, new_priority):
ensure(new_priority >= 0 and new_priority < 4, 'Invalid fee_priority value') ensure(new_priority >= 0 and new_priority < 4, 'Invalid fee_priority value')
self._fee_priority = new_priority self._fee_priority = new_priority
@@ -154,7 +154,7 @@ class XMRInterface(CoinInterface):
pass pass
self.rpc_wallet('open_wallet', params) self.rpc_wallet('open_wallet', params)
def initialiseWallet(self, key_view: bytes, key_spend: bytes, restore_height=None) -> None: def initialiseWallet(self, key_view, key_spend, restore_height=None):
with self._mx_wallet: with self._mx_wallet:
try: try:
self.openWallet(self._wallet_filename) self.openWallet(self._wallet_filename)
@@ -165,7 +165,7 @@ class XMRInterface(CoinInterface):
Kbv = self.getPubkey(key_view) Kbv = self.getPubkey(key_view)
Kbs = self.getPubkey(key_spend) Kbs = self.getPubkey(key_spend)
address_b58 = xmr_util.encode_address(Kbv, Kbs, self._addr_prefix) address_b58 = xmr_util.encode_address(Kbv, Kbs)
params = { params = {
'filename': self._wallet_filename, 'filename': self._wallet_filename,
@@ -231,13 +231,15 @@ class XMRInterface(CoinInterface):
rv = {} rv = {}
self.rpc_wallet('refresh') self.rpc_wallet('refresh')
balance_info = self.rpc_wallet('get_balance') balance_info = self.rpc_wallet('get_balance')
rv['balance'] = self.format_amount(balance_info['unlocked_balance']) rv['balance'] = self.format_amount(balance_info['unlocked_balance'])
rv['unconfirmed_balance'] = self.format_amount(balance_info['balance'] - balance_info['unlocked_balance']) rv['unconfirmed_balance'] = self.format_amount(balance_info['balance'] - balance_info['unlocked_balance'])
rv['encrypted'] = False if self._wallet_password is None else True rv['encrypted'] = False if self._wallet_password is None else True
rv['locked'] = False rv['locked'] = False
return rv return rv
def walletRestoreHeight(self):
return self._restore_height
def getMainWalletAddress(self) -> str: def getMainWalletAddress(self) -> str:
with self._mx_wallet: with self._mx_wallet:
self.openWallet(self._wallet_filename) self.openWallet(self._wallet_filename)
@@ -251,15 +253,8 @@ class XMRInterface(CoinInterface):
return new_address return new_address
def get_fee_rate(self, conf_target: int = 2): def get_fee_rate(self, conf_target: int = 2):
# fees - array of unsigned int; Represents the base fees at different priorities [slow, normal, fast, fastest]. self._log.warning('TODO - estimate XMR fee rate?')
fee_est = self.rpc('get_fee_estimate') return 0.0, 'unused'
if conf_target <= 1:
conf_target = 1 # normal
else:
conf_target = 0 # slow
fee_per_k_bytes = fee_est['fees'][conf_target] * 1000
return float(self.format_amount(fee_per_k_bytes)), 'get_fee_estimate'
def getNewSecretKey(self) -> bytes: def getNewSecretKey(self) -> bytes:
# Note: Returned bytes are in big endian order # Note: Returned bytes are in big endian order
@@ -286,7 +281,7 @@ class XMRInterface(CoinInterface):
def getAddressFromKeys(self, key_view: bytes, key_spend: bytes) -> str: def getAddressFromKeys(self, key_view: bytes, key_spend: bytes) -> str:
pk_view = self.getPubkey(key_view) pk_view = self.getPubkey(key_view)
pk_spend = self.getPubkey(key_spend) pk_spend = self.getPubkey(key_spend)
return xmr_util.encode_address(pk_view, pk_spend, self._addr_prefix) return xmr_util.encode_address(pk_view, pk_spend)
def verifyKey(self, k: int) -> bool: def verifyKey(self, k: int) -> bool:
i = b2i(k) i = b2i(k)
@@ -314,15 +309,15 @@ class XMRInterface(CoinInterface):
return ed25519_add(Ka, Kb) return ed25519_add(Ka, Kb)
def encodeSharedAddress(self, Kbv: bytes, Kbs: bytes) -> str: def encodeSharedAddress(self, Kbv: bytes, Kbs: bytes) -> str:
return xmr_util.encode_address(Kbv, Kbs, self._addr_prefix) return xmr_util.encode_address(Kbv, Kbs)
def publishBLockTx(self, kbv: bytes, Kbs: bytes, output_amount: int, feerate: int, unlock_time: int = 0) -> bytes: def publishBLockTx(self, kbv: bytes, Kbs: bytes, output_amount: int, feerate: int, delay_for: int = 10, unlock_time: int = 0) -> bytes:
with self._mx_wallet: with self._mx_wallet:
self.openWallet(self._wallet_filename) self.openWallet(self._wallet_filename)
self.rpc_wallet('refresh') self.rpc_wallet('refresh')
Kbv = self.getPubkey(kbv) Kbv = self.getPubkey(kbv)
shared_addr = xmr_util.encode_address(Kbv, Kbs, self._addr_prefix) shared_addr = xmr_util.encode_address(Kbv, Kbs)
params = {'destinations': [{'amount': output_amount, 'address': shared_addr}], 'unlock_time': unlock_time} params = {'destinations': [{'amount': output_amount, 'address': shared_addr}], 'unlock_time': unlock_time}
if self._fee_priority > 0: if self._fee_priority > 0:
@@ -331,12 +326,24 @@ class XMRInterface(CoinInterface):
self._log.info('publishBLockTx %s to address_b58 %s', rv['tx_hash'], shared_addr) self._log.info('publishBLockTx %s to address_b58 %s', rv['tx_hash'], shared_addr)
tx_hash = bytes.fromhex(rv['tx_hash']) tx_hash = bytes.fromhex(rv['tx_hash'])
if self._sc.debug:
i = 0
while not self._sc.delay_event.is_set():
gt_params = {'out': True, 'pending': True, 'failed': True, 'pool': True, }
rv = self.rpc_wallet('get_transfers', gt_params)
self._log.debug('get_transfers {}'.format(dumpj(rv)))
if 'pending' not in rv:
break
if i >= delay_for:
break
self._sc.delay_event.wait(1.0)
return tx_hash return tx_hash
def findTxB(self, kbv, Kbs, cb_swap_value, cb_block_confirmed, restore_height, bid_sender): def findTxB(self, kbv, Kbs, cb_swap_value, cb_block_confirmed, restore_height, bid_sender):
with self._mx_wallet: with self._mx_wallet:
Kbv = self.getPubkey(kbv) Kbv = self.getPubkey(kbv)
address_b58 = xmr_util.encode_address(Kbv, Kbs, self._addr_prefix) address_b58 = xmr_util.encode_address(Kbv, Kbs)
kbv_le = kbv[::-1] kbv_le = kbv[::-1]
params = { params = {
@@ -406,7 +413,7 @@ class XMRInterface(CoinInterface):
return None return None
def spendBLockTx(self, chain_b_lock_txid: bytes, address_to: str, kbv: bytes, kbs: bytes, cb_swap_value: int, b_fee_rate: int, restore_height: int, spend_actual_balance: bool = False, lock_tx_vout=None) -> bytes: def spendBLockTx(self, chain_b_lock_txid: bytes, address_to: str, kbv: bytes, kbs: bytes, cb_swap_value: int, b_fee_rate: int, restore_height: int, spend_actual_balance: bool = False) -> bytes:
''' '''
Notes: Notes:
"Error: No unlocked balance in the specified subaddress(es)" can mean not enough funds after tx fee. "Error: No unlocked balance in the specified subaddress(es)" can mean not enough funds after tx fee.
@@ -414,7 +421,7 @@ class XMRInterface(CoinInterface):
with self._mx_wallet: with self._mx_wallet:
Kbv = self.getPubkey(kbv) Kbv = self.getPubkey(kbv)
Kbs = self.getPubkey(kbs) Kbs = self.getPubkey(kbs)
address_b58 = xmr_util.encode_address(Kbv, Kbs, self._addr_prefix) address_b58 = xmr_util.encode_address(Kbv, Kbs)
wallet_filename = address_b58 + '_spend' wallet_filename = address_b58 + '_spend'
@@ -466,42 +473,36 @@ class XMRInterface(CoinInterface):
return bytes.fromhex(rv['tx_hash_list'][0]) return bytes.fromhex(rv['tx_hash_list'][0])
def withdrawCoin(self, value, addr_to: str, sweepall: bool, estimate_fee: bool = False) -> str: def withdrawCoin(self, value: int, addr_to: str, subfee: bool) -> str:
with self._mx_wallet: with self._mx_wallet:
value_sats = make_int(value, self.exp())
self.openWallet(self._wallet_filename) self.openWallet(self._wallet_filename)
self.rpc_wallet('refresh') self.rpc_wallet('refresh')
if sweepall: if subfee:
balance = self.rpc_wallet('get_balance') balance = self.rpc_wallet('get_balance')
if balance['balance'] != balance['unlocked_balance']: diff = balance['unlocked_balance'] - value_sats
raise ValueError('Balance must be fully confirmed to use sweep all.') if diff >= 0 and diff <= 10:
self._log.info('XMR {} sweep_all.'.format('estimate fee' if estimate_fee else 'withdraw')) self._log.info('subfee enabled and value close to total, using sweep_all.')
self._log.debug('XMR balance: {}'.format(balance['balance'])) params = {'address': addr_to}
params = {'address': addr_to, 'do_not_relay': estimate_fee}
if self._fee_priority > 0: if self._fee_priority > 0:
params['priority'] = self._fee_priority params['priority'] = self._fee_priority
rv = self.rpc_wallet('sweep_all', params) rv = self.rpc_wallet('sweep_all', params)
if estimate_fee:
return {'num_txns': len(rv['fee_list']), 'sum_amount': sum(rv['amount_list']), 'sum_fee': sum(rv['fee_list']), 'sum_weight': sum(rv['weight_list'])}
return rv['tx_hash_list'][0] return rv['tx_hash_list'][0]
raise ValueError('Withdraw value must be close to total to use subfee/sweep_all.')
value_sats: int = self.make_int(value) params = {'destinations': [{'amount': value_sats, 'address': addr_to}]}
params = {'destinations': [{'amount': value_sats, 'address': addr_to}], 'do_not_relay': estimate_fee}
if self._fee_priority > 0: if self._fee_priority > 0:
params['priority'] = self._fee_priority params['priority'] = self._fee_priority
rv = self.rpc_wallet('transfer', params) rv = self.rpc_wallet('transfer', params)
if estimate_fee:
return {'num_txns': 1, 'sum_amount': rv['amount'], 'sum_fee': rv['fee'], 'sum_weight': rv['weight']}
return rv['tx_hash'] return rv['tx_hash']
def estimateFee(self, value: int, addr_to: str, sweepall: bool) -> str:
return self.withdrawCoin(value, addr_to, sweepall, estimate_fee=True)
def showLockTransfers(self, kbv, Kbs, restore_height): def showLockTransfers(self, kbv, Kbs, restore_height):
with self._mx_wallet: with self._mx_wallet:
try: try:
Kbv = self.getPubkey(kbv) Kbv = self.getPubkey(kbv)
address_b58 = xmr_util.encode_address(Kbv, Kbs, self._addr_prefix) address_b58 = xmr_util.encode_address(Kbv, Kbs)
wallet_file = address_b58 + '_spend' wallet_file = address_b58 + '_spend'
try: try:
self.openWallet(wallet_file) self.openWallet(wallet_file)

View File

@@ -52,17 +52,9 @@ def getFormData(post_string: str, is_json: bool):
def withdraw_coin(swap_client, coin_type, post_string, is_json): def withdraw_coin(swap_client, coin_type, post_string, is_json):
post_data = getFormData(post_string, is_json) post_data = getFormData(post_string, is_json)
address = get_data_entry(post_data, 'address')
if coin_type == Coins.XMR:
value = None
sweepall = get_data_entry(post_data, 'sweepall')
if not isinstance(sweepall, bool):
sweepall = toBool(sweepall)
if not sweepall:
value = get_data_entry(post_data, 'value')
else:
value = get_data_entry(post_data, 'value') value = get_data_entry(post_data, 'value')
address = get_data_entry(post_data, 'address')
subfee = get_data_entry(post_data, 'subfee') subfee = get_data_entry(post_data, 'subfee')
if not isinstance(subfee, bool): if not isinstance(subfee, bool):
subfee = toBool(subfee) subfee = toBool(subfee)
@@ -74,8 +66,6 @@ def withdraw_coin(swap_client, coin_type, post_string, is_json):
elif coin_type == Coins.LTC: elif coin_type == Coins.LTC:
type_from = get_data_entry_or(post_data, 'type_from', 'plain') type_from = get_data_entry_or(post_data, 'type_from', 'plain')
txid_hex = swap_client.withdrawLTC(type_from, value, address, subfee) txid_hex = swap_client.withdrawLTC(type_from, value, address, subfee)
elif coin_type == Coins.XMR:
txid_hex = swap_client.withdrawCoin(coin_type, value, address, sweepall)
else: else:
txid_hex = swap_client.withdrawCoin(coin_type, value, address, subfee) txid_hex = swap_client.withdrawCoin(coin_type, value, address, subfee)
@@ -339,10 +329,7 @@ def js_bids(self, url_split, post_string: str, is_json: bool) -> bytes:
extra_options = { extra_options = {
'valid_for_seconds': valid_for_seconds, 'valid_for_seconds': valid_for_seconds,
} }
if have_data_entry(post_data, 'bid_rate'):
if have_data_entry(post_data, 'amount_to'):
extra_options['amount_to'] = inputAmount(get_data_entry(post_data, 'amount_to'), ci_to)
elif have_data_entry(post_data, 'bid_rate'):
extra_options['bid_rate'] = ci_to.make_int(get_data_entry(post_data, 'bid_rate'), r=1) extra_options['bid_rate'] = ci_to.make_int(get_data_entry(post_data, 'bid_rate'), r=1)
if have_data_entry(post_data, 'bid_amount'): if have_data_entry(post_data, 'bid_amount'):
amount_from = inputAmount(get_data_entry(post_data, 'bid_amount'), ci_from) amount_from = inputAmount(get_data_entry(post_data, 'bid_amount'), ci_from)
@@ -496,10 +483,10 @@ def js_rate(self, url_split, post_string, is_json) -> bytes:
amount_from = ci_from.format_amount(int((amt_to * rate) // ci_to.COIN()), r=1) amount_from = ci_from.format_amount(int((amt_to * rate) // ci_to.COIN()), r=1)
return bytes(json.dumps({'amount_from': amount_from}), 'UTF-8') return bytes(json.dumps({'amount_from': amount_from}), 'UTF-8')
amt_from: int = inputAmount(get_data_entry(post_data, 'amt_from'), ci_from) amt_from = inputAmount(get_data_entry(post_data, 'amt_from'), ci_from)
amt_to: int = inputAmount(get_data_entry(post_data, 'amt_to'), ci_to) amt_to = inputAmount(get_data_entry(post_data, 'amt_to'), ci_to)
rate: int = ci_to.format_amount(ci_from.make_int(amt_to / amt_from, r=1)) rate = ci_to.format_amount(ci_from.make_int(amt_to / amt_from, r=1))
return bytes(json.dumps({'rate': rate}), 'UTF-8') return bytes(json.dumps({'rate': rate}), 'UTF-8')
@@ -635,33 +622,6 @@ def js_automationstrategies(self, url_split, post_string: str, is_json: bool) ->
return bytes(json.dumps(rv), 'UTF-8') return bytes(json.dumps(rv), 'UTF-8')
def js_validateamount(self, url_split, post_string: str, is_json: bool) -> bytes:
swap_client = self.server.swap_client
swap_client.checkSystemStatus()
post_data = getFormData(post_string, is_json)
ticker_str = post_data['coin']
amount = post_data['amount']
round_method = post_data.get('method', 'none')
valid_round_methods = ('roundoff', 'rounddown', 'none')
if round_method not in valid_round_methods:
raise ValueError(f'Unknown rounding method, must be one of {valid_round_methods}')
coin_type = tickerToCoinId(ticker_str)
ci = swap_client.ci(coin_type)
r = 0
if round_method == 'roundoff':
r = 1
elif round_method == 'rounddown':
r = -1
output_amount = ci.format_amount(amount, conv_int=True, r=r)
return bytes(json.dumps(output_amount), 'UTF-8')
def js_vacuumdb(self, url_split, post_string, is_json) -> bytes: def js_vacuumdb(self, url_split, post_string, is_json) -> bytes:
swap_client = self.server.swap_client swap_client = self.server.swap_client
swap_client.checkSystemStatus() swap_client.checkSystemStatus()
@@ -777,7 +737,6 @@ pages = {
'notifications': js_notifications, 'notifications': js_notifications,
'identities': js_identities, 'identities': js_identities,
'automationstrategies': js_automationstrategies, 'automationstrategies': js_automationstrategies,
'validateamount': js_validateamount,
'vacuumdb': js_vacuumdb, 'vacuumdb': js_vacuumdb,
'getcoinseed': js_getcoinseed, 'getcoinseed': js_getcoinseed,
'setpassword': js_setpassword, 'setpassword': js_setpassword,

View File

@@ -4,13 +4,12 @@ package basicswap;
/* Step 1, seller -> network */ /* Step 1, seller -> network */
message OfferMessage { message OfferMessage {
uint32 protocol_version = 1; uint32 coin_from = 1;
uint32 coin_from = 2; uint32 coin_to = 2;
uint32 coin_to = 3; uint64 amount_from = 3;
uint64 amount_from = 4; uint64 rate = 4;
uint64 amount_to = 5; uint64 min_bid_amount = 5;
uint64 min_bid_amount = 6; uint64 time_valid = 6;
uint64 time_valid = 7;
enum LockType { enum LockType {
NOT_SET = 0; NOT_SET = 0;
SEQUENCE_LOCK_BLOCKS = 1; SEQUENCE_LOCK_BLOCKS = 1;
@@ -18,19 +17,20 @@ message OfferMessage {
ABS_LOCK_BLOCKS = 3; ABS_LOCK_BLOCKS = 3;
ABS_LOCK_TIME = 4; ABS_LOCK_TIME = 4;
} }
LockType lock_type = 8; LockType lock_type = 7;
uint32 lock_value = 9; uint32 lock_value = 8;
uint32 swap_type = 10; uint32 swap_type = 9;
/* optional */ /* optional */
string proof_address = 11; string proof_address = 10;
string proof_signature = 12; string proof_signature = 11;
bytes pkhash_seller = 13; bytes pkhash_seller = 12;
bytes secret_hash = 14; bytes secret_hash = 13;
uint64 fee_rate_from = 15; uint64 fee_rate_from = 14;
uint64 fee_rate_to = 16; uint64 fee_rate_to = 15;
uint32 protocol_version = 16;
bool amount_negotiable = 17; bool amount_negotiable = 17;
bool rate_negotiable = 18; bool rate_negotiable = 18;
@@ -39,36 +39,39 @@ message OfferMessage {
/* Step 2, buyer -> seller */ /* Step 2, buyer -> seller */
message BidMessage { message BidMessage {
uint32 protocol_version = 1; bytes offer_msg_id = 1;
bytes offer_msg_id = 2; uint64 time_valid = 2; /* seconds bid is valid for */
uint64 time_valid = 3; /* seconds bid is valid for */ uint64 amount = 3; /* amount of amount_from bid is for */
uint64 amount = 4; /* amount of amount_from bid is for */ uint64 rate = 4;
uint64 amount_to = 5; bytes pkhash_buyer = 5; /* buyer's address to receive amount_from */
bytes pkhash_buyer = 6; /* buyer's address to receive amount_from */ string proof_address = 6;
string proof_address = 7; string proof_signature = 7;
string proof_signature = 8;
uint32 protocol_version = 8;
bytes proof_utxos = 9; /* 32 byte txid 2 byte vout, repeated */ bytes proof_utxos = 9; /* 32 byte txid 2 byte vout, repeated */
/* optional */
bytes pkhash_buyer_to = 13; /* When pubkey hash is different on the to-chain */
} }
/* For tests */ /* For tests */
message BidMessage_test { message BidMessage_v1Deprecated {
uint32 protocol_version = 1; bytes offer_msg_id = 1;
bytes offer_msg_id = 2; uint64 time_valid = 2; /* seconds bid is valid for */
uint64 time_valid = 3; uint64 amount = 3; /* amount of amount_from bid is for */
uint64 amount = 4; uint64 rate = 4;
uint64 rate = 5; bytes pkhash_buyer = 5; /* buyer's address to receive amount_from */
string proof_address = 6;
string proof_signature = 7;
uint32 protocol_version = 8;
} }
/* Step 3, seller -> buyer */ /* Step 3, seller -> buyer */
message BidAcceptMessage { message BidAcceptMessage {
bytes bid_msg_id = 1; bytes bid_msg_id = 1;
bytes initiate_txid = 2; bytes initiate_txid = 2;
bytes contract_script = 3; bytes contract_script = 3;
bytes pkhash_seller = 4;
} }
message OfferRevokeMessage { message OfferRevokeMessage {
@@ -78,23 +81,25 @@ message OfferRevokeMessage {
message BidRejectMessage { message BidRejectMessage {
bytes bid_msg_id = 1; bytes bid_msg_id = 1;
uint32 reject_code = 2; uint32 reject_code = 2;
} }
message XmrBidMessage { message XmrBidMessage {
/* MSG1L, F -> L */ /* MSG1L, F -> L */
uint32 protocol_version = 1; bytes offer_msg_id = 1;
bytes offer_msg_id = 2; uint64 time_valid = 2; /* seconds bid is valid for */
uint64 time_valid = 3; /* seconds bid is valid for */ uint64 amount = 3; /* amount of amount_from bid is for */
uint64 amount = 4; /* amount of amount_from bid is for */ uint64 rate = 4;
uint64 amount_to = 5;
bytes pkaf = 6; bytes pkaf = 5;
bytes kbvf = 7; bytes kbvf = 6;
bytes kbsf_dleag = 8; bytes kbsf_dleag = 7;
bytes dest_af = 9; bytes dest_af = 8;
uint32 protocol_version = 9;
} }
message XmrSplitMessage { message XmrSplitMessage {
@@ -107,22 +112,24 @@ message XmrSplitMessage {
message XmrBidAcceptMessage { message XmrBidAcceptMessage {
bytes bid_msg_id = 1; bytes bid_msg_id = 1;
bytes pkal = 2; bytes pkal = 3;
bytes kbvl = 3;
bytes kbsl_dleag = 4; bytes kbvl = 4;
bytes kbsl_dleag = 5;
/* MSG2F */ /* MSG2F */
bytes a_lock_tx = 5; bytes a_lock_tx = 6;
bytes a_lock_tx_script = 6; bytes a_lock_tx_script = 7;
bytes a_lock_refund_tx = 7; bytes a_lock_refund_tx = 8;
bytes a_lock_refund_tx_script = 8; bytes a_lock_refund_tx_script = 9;
bytes a_lock_refund_spend_tx = 9; bytes a_lock_refund_spend_tx = 10;
bytes al_lock_refund_tx_sig = 10; bytes al_lock_refund_tx_sig = 11;
} }
message XmrBidLockTxSigsMessage { message XmrBidLockTxSigsMessage {
/* MSG3L */ /* MSG3L */
bytes bid_msg_id = 1; bytes bid_msg_id = 1;
bytes af_lock_refund_spend_tx_esig = 2; bytes af_lock_refund_spend_tx_esig = 2;
bytes af_lock_refund_tx_sig = 3; bytes af_lock_refund_tx_sig = 3;
} }
@@ -130,6 +137,7 @@ message XmrBidLockTxSigsMessage {
message XmrBidLockSpendTxMessage { message XmrBidLockSpendTxMessage {
/* MSG4F */ /* MSG4F */
bytes bid_msg_id = 1; bytes bid_msg_id = 1;
bytes a_lock_spend_tx = 2; bytes a_lock_spend_tx = 2;
bytes kal_sig = 3; bytes kal_sig = 3;
} }
@@ -137,16 +145,19 @@ message XmrBidLockSpendTxMessage {
message XmrBidLockReleaseMessage { message XmrBidLockReleaseMessage {
/* MSG5F */ /* MSG5F */
bytes bid_msg_id = 1; bytes bid_msg_id = 1;
bytes al_lock_spend_tx_esig = 2; bytes al_lock_spend_tx_esig = 2;
} }
message ADSBidIntentMessage { message ADSBidIntentMessage {
/* L -> F Sent from bidder, construct a reverse bid */ /* L -> F Sent from bidder, construct a reverse bid */
uint32 protocol_version = 1; bytes offer_msg_id = 1;
bytes offer_msg_id = 2; uint64 time_valid = 2; /* seconds bid is valid for */
uint64 time_valid = 3; /* seconds bid is valid for */ uint64 amount_from = 3; /* amount of offer.coin_from bid is for */
uint64 amount_from = 4; /* amount of offer.coin_from bid is for */ uint64 amount_to = 4; /* amount of offer.coin_to bid is for, equivalent to bid.amount */
uint64 amount_to = 5; /* amount of offer.coin_to bid is for, equivalent to bid.amount */ uint64 rate = 5; /* amount of offer.coin_from bid is for */
uint32 protocol_version = 6;
} }
message ADSBidIntentAcceptMessage { message ADSBidIntentAcceptMessage {

View File

@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT! # Generated by the protocol buffer compiler. DO NOT EDIT!
# source: messages.proto # source: messages.proto
# Protobuf Python Version: 4.25.3
"""Generated protocol buffer code.""" """Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool from google.protobuf import descriptor_pool as _descriptor_pool
@@ -14,7 +13,7 @@ _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0emessages.proto\x12\tbasicswap\"\xc0\x04\n\x0cOfferMessage\x12\x18\n\x10protocol_version\x18\x01 \x01(\r\x12\x11\n\tcoin_from\x18\x02 \x01(\r\x12\x0f\n\x07\x63oin_to\x18\x03 \x01(\r\x12\x13\n\x0b\x61mount_from\x18\x04 \x01(\x04\x12\x11\n\tamount_to\x18\x05 \x01(\x04\x12\x16\n\x0emin_bid_amount\x18\x06 \x01(\x04\x12\x12\n\ntime_valid\x18\x07 \x01(\x04\x12\x33\n\tlock_type\x18\x08 \x01(\x0e\x32 .basicswap.OfferMessage.LockType\x12\x12\n\nlock_value\x18\t \x01(\r\x12\x11\n\tswap_type\x18\n \x01(\r\x12\x15\n\rproof_address\x18\x0b \x01(\t\x12\x17\n\x0fproof_signature\x18\x0c \x01(\t\x12\x15\n\rpkhash_seller\x18\r \x01(\x0c\x12\x13\n\x0bsecret_hash\x18\x0e \x01(\x0c\x12\x15\n\rfee_rate_from\x18\x0f \x01(\x04\x12\x13\n\x0b\x66\x65\x65_rate_to\x18\x10 \x01(\x04\x12\x19\n\x11\x61mount_negotiable\x18\x11 \x01(\x08\x12\x17\n\x0frate_negotiable\x18\x12 \x01(\x08\x12\x13\n\x0bproof_utxos\x18\x13 \x01(\x0c\"q\n\x08LockType\x12\x0b\n\x07NOT_SET\x10\x00\x12\x18\n\x14SEQUENCE_LOCK_BLOCKS\x10\x01\x12\x16\n\x12SEQUENCE_LOCK_TIME\x10\x02\x12\x13\n\x0f\x41\x42S_LOCK_BLOCKS\x10\x03\x12\x11\n\rABS_LOCK_TIME\x10\x04\"\xe7\x01\n\nBidMessage\x12\x18\n\x10protocol_version\x18\x01 \x01(\r\x12\x14\n\x0coffer_msg_id\x18\x02 \x01(\x0c\x12\x12\n\ntime_valid\x18\x03 \x01(\x04\x12\x0e\n\x06\x61mount\x18\x04 \x01(\x04\x12\x11\n\tamount_to\x18\x05 \x01(\x04\x12\x14\n\x0cpkhash_buyer\x18\x06 \x01(\x0c\x12\x15\n\rproof_address\x18\x07 \x01(\t\x12\x17\n\x0fproof_signature\x18\x08 \x01(\t\x12\x13\n\x0bproof_utxos\x18\t \x01(\x0c\x12\x17\n\x0fpkhash_buyer_to\x18\r \x01(\x0c\"s\n\x0f\x42idMessage_test\x12\x18\n\x10protocol_version\x18\x01 \x01(\r\x12\x14\n\x0coffer_msg_id\x18\x02 \x01(\x0c\x12\x12\n\ntime_valid\x18\x03 \x01(\x04\x12\x0e\n\x06\x61mount\x18\x04 \x01(\x04\x12\x0c\n\x04rate\x18\x05 \x01(\x04\"m\n\x10\x42idAcceptMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x15\n\rinitiate_txid\x18\x02 \x01(\x0c\x12\x17\n\x0f\x63ontract_script\x18\x03 \x01(\x0c\x12\x15\n\rpkhash_seller\x18\x04 \x01(\x0c\"=\n\x12OfferRevokeMessage\x12\x14\n\x0coffer_msg_id\x18\x01 \x01(\x0c\x12\x11\n\tsignature\x18\x02 \x01(\x0c\";\n\x10\x42idRejectMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x13\n\x0breject_code\x18\x02 \x01(\r\"\xb7\x01\n\rXmrBidMessage\x12\x18\n\x10protocol_version\x18\x01 \x01(\r\x12\x14\n\x0coffer_msg_id\x18\x02 \x01(\x0c\x12\x12\n\ntime_valid\x18\x03 \x01(\x04\x12\x0e\n\x06\x61mount\x18\x04 \x01(\x04\x12\x11\n\tamount_to\x18\x05 \x01(\x04\x12\x0c\n\x04pkaf\x18\x06 \x01(\x0c\x12\x0c\n\x04kbvf\x18\x07 \x01(\x0c\x12\x12\n\nkbsf_dleag\x18\x08 \x01(\x0c\x12\x0f\n\x07\x64\x65st_af\x18\t \x01(\x0c\"T\n\x0fXmrSplitMessage\x12\x0e\n\x06msg_id\x18\x01 \x01(\x0c\x12\x10\n\x08msg_type\x18\x02 \x01(\r\x12\x10\n\x08sequence\x18\x03 \x01(\r\x12\r\n\x05\x64leag\x18\x04 \x01(\x0c\"\x80\x02\n\x13XmrBidAcceptMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x0c\n\x04pkal\x18\x02 \x01(\x0c\x12\x0c\n\x04kbvl\x18\x03 \x01(\x0c\x12\x12\n\nkbsl_dleag\x18\x04 \x01(\x0c\x12\x11\n\ta_lock_tx\x18\x05 \x01(\x0c\x12\x18\n\x10\x61_lock_tx_script\x18\x06 \x01(\x0c\x12\x18\n\x10\x61_lock_refund_tx\x18\x07 \x01(\x0c\x12\x1f\n\x17\x61_lock_refund_tx_script\x18\x08 \x01(\x0c\x12\x1e\n\x16\x61_lock_refund_spend_tx\x18\t \x01(\x0c\x12\x1d\n\x15\x61l_lock_refund_tx_sig\x18\n \x01(\x0c\"r\n\x17XmrBidLockTxSigsMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12$\n\x1c\x61\x66_lock_refund_spend_tx_esig\x18\x02 \x01(\x0c\x12\x1d\n\x15\x61\x66_lock_refund_tx_sig\x18\x03 \x01(\x0c\"X\n\x18XmrBidLockSpendTxMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x17\n\x0f\x61_lock_spend_tx\x18\x02 \x01(\x0c\x12\x0f\n\x07kal_sig\x18\x03 \x01(\x0c\"M\n\x18XmrBidLockReleaseMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x1d\n\x15\x61l_lock_spend_tx_esig\x18\x02 \x01(\x0c\"\x81\x01\n\x13\x41\x44SBidIntentMessage\x12\x18\n\x10protocol_version\x18\x01 \x01(\r\x12\x14\n\x0coffer_msg_id\x18\x02 \x01(\x0c\x12\x12\n\ntime_valid\x18\x03 \x01(\x04\x12\x13\n\x0b\x61mount_from\x18\x04 \x01(\x04\x12\x11\n\tamount_to\x18\x05 \x01(\x04\"p\n\x19\x41\x44SBidIntentAcceptMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x0c\n\x04pkaf\x18\x02 \x01(\x0c\x12\x0c\n\x04kbvf\x18\x03 \x01(\x0c\x12\x12\n\nkbsf_dleag\x18\x04 \x01(\x0c\x12\x0f\n\x07\x64\x65st_af\x18\x05 \x01(\x0c\x62\x06proto3') DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0emessages.proto\x12\tbasicswap\"\xa6\x04\n\x0cOfferMessage\x12\x11\n\tcoin_from\x18\x01 \x01(\r\x12\x0f\n\x07\x63oin_to\x18\x02 \x01(\r\x12\x13\n\x0b\x61mount_from\x18\x03 \x01(\x04\x12\x0c\n\x04rate\x18\x04 \x01(\x04\x12\x16\n\x0emin_bid_amount\x18\x05 \x01(\x04\x12\x12\n\ntime_valid\x18\x06 \x01(\x04\x12\x33\n\tlock_type\x18\x07 \x01(\x0e\x32 .basicswap.OfferMessage.LockType\x12\x12\n\nlock_value\x18\x08 \x01(\r\x12\x11\n\tswap_type\x18\t \x01(\r\x12\x15\n\rproof_address\x18\n \x01(\t\x12\x17\n\x0fproof_signature\x18\x0b \x01(\t\x12\x15\n\rpkhash_seller\x18\x0c \x01(\x0c\x12\x13\n\x0bsecret_hash\x18\r \x01(\x0c\x12\x15\n\rfee_rate_from\x18\x0e \x01(\x04\x12\x13\n\x0b\x66\x65\x65_rate_to\x18\x0f \x01(\x04\x12\x18\n\x10protocol_version\x18\x10 \x01(\r\x12\x19\n\x11\x61mount_negotiable\x18\x11 \x01(\x08\x12\x17\n\x0frate_negotiable\x18\x12 \x01(\x08\"q\n\x08LockType\x12\x0b\n\x07NOT_SET\x10\x00\x12\x18\n\x14SEQUENCE_LOCK_BLOCKS\x10\x01\x12\x16\n\x12SEQUENCE_LOCK_TIME\x10\x02\x12\x13\n\x0f\x41\x42S_LOCK_BLOCKS\x10\x03\x12\x11\n\rABS_LOCK_TIME\x10\x04\"\xc9\x01\n\nBidMessage\x12\x14\n\x0coffer_msg_id\x18\x01 \x01(\x0c\x12\x12\n\ntime_valid\x18\x02 \x01(\x04\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x04\x12\x0c\n\x04rate\x18\x04 \x01(\x04\x12\x14\n\x0cpkhash_buyer\x18\x05 \x01(\x0c\x12\x15\n\rproof_address\x18\x06 \x01(\t\x12\x17\n\x0fproof_signature\x18\x07 \x01(\t\x12\x18\n\x10protocol_version\x18\x08 \x01(\r\x12\x13\n\x0bproof_utxos\x18\t \x01(\x0c\"\xc1\x01\n\x17\x42idMessage_v1Deprecated\x12\x14\n\x0coffer_msg_id\x18\x01 \x01(\x0c\x12\x12\n\ntime_valid\x18\x02 \x01(\x04\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x04\x12\x0c\n\x04rate\x18\x04 \x01(\x04\x12\x14\n\x0cpkhash_buyer\x18\x05 \x01(\x0c\x12\x15\n\rproof_address\x18\x06 \x01(\t\x12\x17\n\x0fproof_signature\x18\x07 \x01(\t\x12\x18\n\x10protocol_version\x18\x08 \x01(\r\"V\n\x10\x42idAcceptMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x15\n\rinitiate_txid\x18\x02 \x01(\x0c\x12\x17\n\x0f\x63ontract_script\x18\x03 \x01(\x0c\"=\n\x12OfferRevokeMessage\x12\x14\n\x0coffer_msg_id\x18\x01 \x01(\x0c\x12\x11\n\tsignature\x18\x02 \x01(\x0c\";\n\x10\x42idRejectMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x13\n\x0breject_code\x18\x02 \x01(\r\"\xb2\x01\n\rXmrBidMessage\x12\x14\n\x0coffer_msg_id\x18\x01 \x01(\x0c\x12\x12\n\ntime_valid\x18\x02 \x01(\x04\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x04\x12\x0c\n\x04rate\x18\x04 \x01(\x04\x12\x0c\n\x04pkaf\x18\x05 \x01(\x0c\x12\x0c\n\x04kbvf\x18\x06 \x01(\x0c\x12\x12\n\nkbsf_dleag\x18\x07 \x01(\x0c\x12\x0f\n\x07\x64\x65st_af\x18\x08 \x01(\x0c\x12\x18\n\x10protocol_version\x18\t \x01(\r\"T\n\x0fXmrSplitMessage\x12\x0e\n\x06msg_id\x18\x01 \x01(\x0c\x12\x10\n\x08msg_type\x18\x02 \x01(\r\x12\x10\n\x08sequence\x18\x03 \x01(\r\x12\r\n\x05\x64leag\x18\x04 \x01(\x0c\"\x80\x02\n\x13XmrBidAcceptMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x0c\n\x04pkal\x18\x03 \x01(\x0c\x12\x0c\n\x04kbvl\x18\x04 \x01(\x0c\x12\x12\n\nkbsl_dleag\x18\x05 \x01(\x0c\x12\x11\n\ta_lock_tx\x18\x06 \x01(\x0c\x12\x18\n\x10\x61_lock_tx_script\x18\x07 \x01(\x0c\x12\x18\n\x10\x61_lock_refund_tx\x18\x08 \x01(\x0c\x12\x1f\n\x17\x61_lock_refund_tx_script\x18\t \x01(\x0c\x12\x1e\n\x16\x61_lock_refund_spend_tx\x18\n \x01(\x0c\x12\x1d\n\x15\x61l_lock_refund_tx_sig\x18\x0b \x01(\x0c\"r\n\x17XmrBidLockTxSigsMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12$\n\x1c\x61\x66_lock_refund_spend_tx_esig\x18\x02 \x01(\x0c\x12\x1d\n\x15\x61\x66_lock_refund_tx_sig\x18\x03 \x01(\x0c\"X\n\x18XmrBidLockSpendTxMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x17\n\x0f\x61_lock_spend_tx\x18\x02 \x01(\x0c\x12\x0f\n\x07kal_sig\x18\x03 \x01(\x0c\"M\n\x18XmrBidLockReleaseMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x1d\n\x15\x61l_lock_spend_tx_esig\x18\x02 \x01(\x0c\"\x8f\x01\n\x13\x41\x44SBidIntentMessage\x12\x14\n\x0coffer_msg_id\x18\x01 \x01(\x0c\x12\x12\n\ntime_valid\x18\x02 \x01(\x04\x12\x13\n\x0b\x61mount_from\x18\x03 \x01(\x04\x12\x11\n\tamount_to\x18\x04 \x01(\x04\x12\x0c\n\x04rate\x18\x05 \x01(\x04\x12\x18\n\x10protocol_version\x18\x06 \x01(\r\"p\n\x19\x41\x44SBidIntentAcceptMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x0c\n\x04pkaf\x18\x02 \x01(\x0c\x12\x0c\n\x04kbvf\x18\x03 \x01(\x0c\x12\x12\n\nkbsf_dleag\x18\x04 \x01(\x0c\x12\x0f\n\x07\x64\x65st_af\x18\x05 \x01(\x0c\x62\x06proto3')
_globals = globals() _globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -22,33 +21,33 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'messages_pb2', _globals)
if _descriptor._USE_C_DESCRIPTORS == False: if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None DESCRIPTOR._options = None
_globals['_OFFERMESSAGE']._serialized_start=30 _globals['_OFFERMESSAGE']._serialized_start=30
_globals['_OFFERMESSAGE']._serialized_end=606 _globals['_OFFERMESSAGE']._serialized_end=580
_globals['_OFFERMESSAGE_LOCKTYPE']._serialized_start=493 _globals['_OFFERMESSAGE_LOCKTYPE']._serialized_start=467
_globals['_OFFERMESSAGE_LOCKTYPE']._serialized_end=606 _globals['_OFFERMESSAGE_LOCKTYPE']._serialized_end=580
_globals['_BIDMESSAGE']._serialized_start=609 _globals['_BIDMESSAGE']._serialized_start=583
_globals['_BIDMESSAGE']._serialized_end=840 _globals['_BIDMESSAGE']._serialized_end=784
_globals['_BIDMESSAGE_TEST']._serialized_start=842 _globals['_BIDMESSAGE_V1DEPRECATED']._serialized_start=787
_globals['_BIDMESSAGE_TEST']._serialized_end=957 _globals['_BIDMESSAGE_V1DEPRECATED']._serialized_end=980
_globals['_BIDACCEPTMESSAGE']._serialized_start=959 _globals['_BIDACCEPTMESSAGE']._serialized_start=982
_globals['_BIDACCEPTMESSAGE']._serialized_end=1068 _globals['_BIDACCEPTMESSAGE']._serialized_end=1068
_globals['_OFFERREVOKEMESSAGE']._serialized_start=1070 _globals['_OFFERREVOKEMESSAGE']._serialized_start=1070
_globals['_OFFERREVOKEMESSAGE']._serialized_end=1131 _globals['_OFFERREVOKEMESSAGE']._serialized_end=1131
_globals['_BIDREJECTMESSAGE']._serialized_start=1133 _globals['_BIDREJECTMESSAGE']._serialized_start=1133
_globals['_BIDREJECTMESSAGE']._serialized_end=1192 _globals['_BIDREJECTMESSAGE']._serialized_end=1192
_globals['_XMRBIDMESSAGE']._serialized_start=1195 _globals['_XMRBIDMESSAGE']._serialized_start=1195
_globals['_XMRBIDMESSAGE']._serialized_end=1378 _globals['_XMRBIDMESSAGE']._serialized_end=1373
_globals['_XMRSPLITMESSAGE']._serialized_start=1380 _globals['_XMRSPLITMESSAGE']._serialized_start=1375
_globals['_XMRSPLITMESSAGE']._serialized_end=1464 _globals['_XMRSPLITMESSAGE']._serialized_end=1459
_globals['_XMRBIDACCEPTMESSAGE']._serialized_start=1467 _globals['_XMRBIDACCEPTMESSAGE']._serialized_start=1462
_globals['_XMRBIDACCEPTMESSAGE']._serialized_end=1723 _globals['_XMRBIDACCEPTMESSAGE']._serialized_end=1718
_globals['_XMRBIDLOCKTXSIGSMESSAGE']._serialized_start=1725 _globals['_XMRBIDLOCKTXSIGSMESSAGE']._serialized_start=1720
_globals['_XMRBIDLOCKTXSIGSMESSAGE']._serialized_end=1839 _globals['_XMRBIDLOCKTXSIGSMESSAGE']._serialized_end=1834
_globals['_XMRBIDLOCKSPENDTXMESSAGE']._serialized_start=1841 _globals['_XMRBIDLOCKSPENDTXMESSAGE']._serialized_start=1836
_globals['_XMRBIDLOCKSPENDTXMESSAGE']._serialized_end=1929 _globals['_XMRBIDLOCKSPENDTXMESSAGE']._serialized_end=1924
_globals['_XMRBIDLOCKRELEASEMESSAGE']._serialized_start=1931 _globals['_XMRBIDLOCKRELEASEMESSAGE']._serialized_start=1926
_globals['_XMRBIDLOCKRELEASEMESSAGE']._serialized_end=2008 _globals['_XMRBIDLOCKRELEASEMESSAGE']._serialized_end=2003
_globals['_ADSBIDINTENTMESSAGE']._serialized_start=2011 _globals['_ADSBIDINTENTMESSAGE']._serialized_start=2006
_globals['_ADSBIDINTENTMESSAGE']._serialized_end=2140 _globals['_ADSBIDINTENTMESSAGE']._serialized_end=2149
_globals['_ADSBIDINTENTACCEPTMESSAGE']._serialized_start=2142 _globals['_ADSBIDINTENTACCEPTMESSAGE']._serialized_start=2151
_globals['_ADSBIDINTENTACCEPTMESSAGE']._serialized_end=2254 _globals['_ADSBIDINTENTACCEPTMESSAGE']._serialized_end=2263
# @@protoc_insertion_point(module_scope) # @@protoc_insertion_point(module_scope)

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2020-2024 tecnovert # Copyright (c) 2020-2023 tecnovert
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php. # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@@ -10,15 +10,12 @@ from basicswap.db import (
from basicswap.util import ( from basicswap.util import (
SerialiseNum, SerialiseNum,
) )
from basicswap.util.script import (
decodeScriptNum,
)
from basicswap.script import ( from basicswap.script import (
OpCodes, OpCodes,
) )
from basicswap.basicswap_util import ( from basicswap.basicswap_util import (
EventLogTypes,
SwapTypes, SwapTypes,
EventLogTypes,
) )
from . import ProtocolInterface from . import ProtocolInterface
@@ -26,13 +23,13 @@ INITIATE_TX_TIMEOUT = 40 * 60 # TODO: make variable per coin
ABS_LOCK_TIME_LEEWAY = 10 * 60 ABS_LOCK_TIME_LEEWAY = 10 * 60
def buildContractScript(lock_val: int, secret_hash: bytes, pkh_redeem: bytes, pkh_refund: bytes, op_lock=OpCodes.OP_CHECKSEQUENCEVERIFY, op_hash=OpCodes.OP_SHA256) -> bytearray: def buildContractScript(lock_val: int, secret_hash: bytes, pkh_redeem: bytes, pkh_refund: bytes, op_lock=OpCodes.OP_CHECKSEQUENCEVERIFY) -> bytearray:
script = bytearray([ script = bytearray([
OpCodes.OP_IF, OpCodes.OP_IF,
OpCodes.OP_SIZE, OpCodes.OP_SIZE,
0x01, 0x20, # 32 0x01, 0x20, # 32
OpCodes.OP_EQUALVERIFY, OpCodes.OP_EQUALVERIFY,
op_hash, OpCodes.OP_SHA256,
0x20]) \ 0x20]) \
+ secret_hash \ + secret_hash \
+ bytearray([ + bytearray([
@@ -57,46 +54,6 @@ def buildContractScript(lock_val: int, secret_hash: bytes, pkh_redeem: bytes, pk
return script return script
def verifyContractScript(script, op_lock=OpCodes.OP_CHECKSEQUENCEVERIFY, op_hash=OpCodes.OP_SHA256):
if script[0] != OpCodes.OP_IF or \
script[1] != OpCodes.OP_SIZE or \
script[2] != 0x01 or script[3] != 0x20 or \
script[4] != OpCodes.OP_EQUALVERIFY or \
script[5] != op_hash or \
script[6] != 0x20:
return False, None, None, None, None
o = 7
script_hash = script[o: o + 32]
o += 32
if script[o] != OpCodes.OP_EQUALVERIFY or \
script[o + 1] != OpCodes.OP_DUP or \
script[o + 2] != OpCodes.OP_HASH160 or \
script[o + 3] != 0x14:
return False, script_hash, None, None, None
o += 4
pkh_redeem = script[o: o + 20]
o += 20
if script[o] != OpCodes.OP_ELSE:
return False, script_hash, pkh_redeem, None, None
o += 1
lock_val, nb = decodeScriptNum(script, o)
o += nb
if script[o] != op_lock or \
script[o + 1] != OpCodes.OP_DROP or \
script[o + 2] != OpCodes.OP_DUP or \
script[o + 3] != OpCodes.OP_HASH160 or \
script[o + 4] != 0x14:
return False, script_hash, pkh_redeem, lock_val, None
o += 5
pkh_refund = script[o: o + 20]
o += 20
if script[o] != OpCodes.OP_ENDIF or \
script[o + 1] != OpCodes.OP_EQUALVERIFY or \
script[o + 2] != OpCodes.OP_CHECKSIG:
return False, script_hash, pkh_redeem, lock_val, pkh_refund
return True, script_hash, pkh_redeem, lock_val, pkh_refund
def extractScriptSecretHash(script): def extractScriptSecretHash(script):
return script[7:39] return script[7:39]

View File

@@ -9,7 +9,7 @@ from sqlalchemy.orm import scoped_session
from basicswap.util import ( from basicswap.util import (
ensure, ensure,
) )
from basicswap.interface.base import Curves from basicswap.interface import Curves
from basicswap.chainparams import ( from basicswap.chainparams import (
Coins, Coins,
) )
@@ -21,17 +21,13 @@ from basicswap.basicswap_util import (
from . import ProtocolInterface from . import ProtocolInterface
from basicswap.contrib.test_framework.script import ( from basicswap.contrib.test_framework.script import (
CScript, CScriptOp, CScript, CScriptOp,
OP_CHECKMULTISIG OP_CHECKMULTISIG)
)
def addLockRefundSigs(self, xmr_swap, ci): def addLockRefundSigs(self, xmr_swap, ci):
self.log.debug('Setting lock refund tx sigs') self.log.debug('Setting lock refund tx sigs')
witness_stack = [
witness_stack = [] b'',
if ci.coin_type() not in (Coins.DCR, ):
witness_stack += [b'', ]
witness_stack += [
xmr_swap.al_lock_refund_tx_sig, xmr_swap.al_lock_refund_tx_sig,
xmr_swap.af_lock_refund_tx_sig, xmr_swap.af_lock_refund_tx_sig,
xmr_swap.a_lock_tx_script, xmr_swap.a_lock_tx_script,
@@ -78,8 +74,7 @@ def recoverNoScriptTxnWithKey(self, bid_id: bytes, encoded_key):
address_to = self.getCachedStealthAddressForCoin(offer.coin_to) address_to = self.getCachedStealthAddressForCoin(offer.coin_to)
amount = bid.amount_to amount = bid.amount_to
lock_tx_vout = bid.getLockTXBVout() txid = ci_to.spendBLockTx(xmr_swap.b_lock_tx_id, address_to, xmr_swap.vkbv, vkbs, bid.amount_to, xmr_offer.b_fee_rate, bid.chain_b_height_start, spend_actual_balance=True)
txid = ci_to.spendBLockTx(xmr_swap.b_lock_tx_id, address_to, xmr_swap.vkbv, vkbs, amount, xmr_offer.b_fee_rate, bid.chain_b_height_start, spend_actual_balance=True, lock_tx_vout=lock_tx_vout)
self.log.debug('Submitted lock B spend txn %s to %s chain for bid %s', txid.hex(), ci_to.coin_name(), bid_id.hex()) self.log.debug('Submitted lock B spend txn %s to %s chain for bid %s', txid.hex(), ci_to.coin_name(), bid_id.hex())
self.logBidEvent(bid.bid_id, EventLogTypes.LOCK_TX_B_SPEND_TX_PUBLISHED, txid.hex(), session) self.logBidEvent(bid.bid_id, EventLogTypes.LOCK_TX_B_SPEND_TX_PUBLISHED, txid.hex(), session)
session.commit() session.commit()

View File

@@ -1,13 +1,15 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2020-2024 tecnovert # Copyright (c) 2020-2023 tecnovert
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php. # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
import os import os
import time
import json import json
import shlex import shlex
import urllib import urllib
import logging
import traceback import traceback
import subprocess import subprocess
from xmlrpc.client import ( from xmlrpc.client import (
@@ -18,6 +20,18 @@ from xmlrpc.client import (
from .util import jsonDecimal from .util import jsonDecimal
def waitForRPC(rpc_func, expect_wallet=True, max_tries=7):
for i in range(max_tries + 1):
try:
rpc_func('getwalletinfo' if expect_wallet else 'getblockchaininfo')
return
except Exception as ex:
if i < max_tries:
logging.warning('Can\'t connect to RPC: %s. Retrying in %d second/s.', str(ex), (i + 1))
time.sleep(i + 1)
raise ValueError('waitForRPC failed')
class Jsonrpc(): class Jsonrpc():
# __getattr__ complicates extending ServerProxy # __getattr__ complicates extending ServerProxy
def __init__(self, uri, transport=None, encoding=None, verbose=False, def __init__(self, uri, transport=None, encoding=None, verbose=False,

View File

@@ -26,5 +26,3 @@ class OpCodes(IntEnum):
OP_CHECKSIG = 0xac, OP_CHECKSIG = 0xac,
OP_CHECKLOCKTIMEVERIFY = 0xb1, OP_CHECKLOCKTIMEVERIFY = 0xb1,
OP_CHECKSEQUENCEVERIFY = 0xb2, OP_CHECKSEQUENCEVERIFY = 0xb2,
OP_SHA256_DECRED = 0xc0,

View File

@@ -24,6 +24,7 @@
.error_msg .error_msg
{ {
color:red;
} }
#hide { #hide {
@@ -116,13 +117,14 @@
} }
} }
/* Add this to your existing CSS file */
.error { .error {
border: 1px solid red !important; border: 1px solid red !important;
} }
.active-container { .active-container {
position: relative; position: relative;
border-radius: 10px; border-radius: 5px;
} }
.active-container::before { .active-container::before {
@@ -137,139 +139,3 @@
pointer-events: none; pointer-events: none;
} }
.center-spin {
display: flex;
justify-content: center;
align-items: center;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.hover-container:hover #coin_to_button, .hover-container:hover #coin_to {
border-color: #3b82f6;
}
.hover-container:hover #coin_from_button, .hover-container:hover #coin_from {
border-color: #3b82f6;
}
#coin_to_button, #coin_from_button {
background-repeat: no-repeat;
background-position: center;
background-size: 20px 20px;
}
.input-like-container {
max-width: 100%;
background-color: #ffffff;
width: 360px;
padding: 1rem;
color: #374151;
border-radius: 0.375rem;
font-size: 0.875rem;
line-height: 1.25rem;
outline: none;
word-wrap: break-word;
height: 90px;
color: #374151;
border-radius: 0.375rem;
font-size: 0.875rem;
line-height: 1.25rem;
outline: none;
word-break: break-all;
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.input-like-container.copying {
width: inherit;
}
.qrcode {
position: relative;
display: inline-block;
padding: 10px;
overflow: hidden;
position: relative;
}
.qrcode-border {
border: 2px solid;
border-color: rgba(59, 130, 246, var(--tw-border-opacity));
border-radius: 20px;
}
.qrcode img {
width: 100%;
height: auto;
border-radius: 15px;
}
#showQR {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
height:25px;
}
select.select-disabled {
opacity: 0.40 !important;
}
.disabled-input-enabled {
opacity: 0.40 !important;
}
select.disabled-select-enabled {
opacity: 0.40 !important;
}
.custom-select .select {
appearance: none;
background-position: 10px center;
background-repeat: no-repeat;
position: relative;
}
.custom-select select::-webkit-scrollbar {
width: 0;
}
.custom-select .select option {
padding-left: 0;
text-indent: 0;
background-repeat: no-repeat;
background-position: 0 50%;
}
.custom-select .select option.no-space {
padding-left: 0;
}
.custom-select .select option[data-image] {
background-image: url('');
}
.custom-select .select-icon {
position: absolute;
top: 50%;
left: 10px;
transform: translateY(-50%);
}
.custom-select .select-image {
display: none;
margin-top: 10px;
}
.custom-select .select:focus+.select-dropdown .select-image {
display: block;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

View File

@@ -1,68 +1,70 @@
document.addEventListener('DOMContentLoaded', () => { // Define a cache object to store selected option data
const selectCache = {};
const selectCache = {}; // Function to update the cache with the selected option data for a given select element
function updateSelectCache(select) {
function updateSelectCache(select) {
const selectedOption = select.options[select.selectedIndex]; const selectedOption = select.options[select.selectedIndex];
const image = selectedOption.getAttribute('data-image'); const image = selectedOption.getAttribute('data-image');
const name = selectedOption.textContent.trim(); const name = selectedOption.textContent.trim();
selectCache[select.id] = { image, name }; selectCache[select.id] = { image, name };
} }
function setSelectData(select) { // Function to set the selected option and associated image and name for a given select element
function setSelectData(select) {
const selectedOption = select.options[select.selectedIndex]; const selectedOption = select.options[select.selectedIndex];
const image = selectedOption.getAttribute('data-image') || ''; const image = selectedOption.getAttribute('data-image') || '/static/images/other/coin.png'; // set a default image URL
const name = selectedOption.textContent.trim(); 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;
}
const selectNameElement = select.nextElementSibling.querySelector('.select-name');
if (selectNameElement) {
selectNameElement.textContent = name;
}
updateSelectCache(select);
}
const selectIcons = document.querySelectorAll('.custom-select .select-icon');
const selectImages = document.querySelectorAll('.custom-select .select-image');
const selectNames = document.querySelectorAll('.custom-select .select-name');
selectIcons.forEach(icon => icon.style.display = 'none');
selectImages.forEach(image => image.style.display = 'none');
selectNames.forEach(name => name.style.display = 'none');
function setupCustomSelect(select) {
const options = select.querySelectorAll('option');
const selectIcon = select.parentElement.querySelector('.select-icon');
const selectImage = select.parentElement.querySelector('.select-image');
options.forEach(option => {
const image = option.getAttribute('data-image');
if (image) { if (image) {
option.style.backgroundImage = `url(${image})`; select.style.backgroundImage = `url(${image})`;
select.nextElementSibling.querySelector('.select-image').src = image;
} else {
select.style.backgroundImage = '';
select.nextElementSibling.querySelector('.select-image').src = '';
} }
}); select.nextElementSibling.querySelector('.select-name').textContent = name;
updateSelectCache(select);
}
const storedValue = localStorage.getItem(select.name);
if (storedValue && select.value == '-1') { // Function to get the selected option data from cache for a given select element
select.value = storedValue; function getSelectData(select) {
return selectCache[select.id] || {};
}
// Update all custom select elements on the page
const selects = document.querySelectorAll('.custom-select .select');
selects.forEach((select) => {
// Set the initial select data based on the cached data (if available) or the selected option (if any)
const cachedData = getSelectData(select);
if (cachedData.image) {
select.style.backgroundImage = `url(${cachedData.image})`;
select.nextElementSibling.querySelector('.select-image').src = cachedData.image;
}
if (cachedData.name) {
select.nextElementSibling.querySelector('.select-name').textContent = cachedData.name;
}
if (select.selectedIndex >= 0) {
setSelectData(select);
} }
// Add event listener to update select data when an option is selected
select.addEventListener('change', () => { select.addEventListener('change', () => {
setSelectData(select); setSelectData(select);
localStorage.setItem(select.name, select.value);
}); });
});
setSelectData(select);
selectIcon.style.display = 'none'; // Hide the select image and name on page load
selectImage.style.display = 'none'; const selectIcons = document.querySelectorAll('.custom-select .select-icon');
} const selectImages = document.querySelectorAll('.custom-select .select-image');
const selectNames = document.querySelectorAll('.custom-select .select-name');
const customSelects = document.querySelectorAll('.custom-select select'); selectIcons.forEach((icon) => {
customSelects.forEach(setupCustomSelect); icon.style.display = 'none';
});
selectImages.forEach((image) => {
image.style.display = 'none';
});
selectNames.forEach((name) => {
name.style.display = 'none';
}); });

View File

@@ -0,0 +1,60 @@
// Define the function for setting up the custom select element
function setupCustomSelect(select) {
const options = select.querySelectorAll('option');
const selectIcon = select.parentElement.querySelector('.select-icon');
const selectImage = select.parentElement.querySelector('.select-image');
// Set the background image for each option that has a data-image attribute
options.forEach(option => {
const image = option.getAttribute('data-image');
if (image) {
option.style.backgroundImage = `url(${image})`;
}
});
if (select.value == '-1') {
// Set the selected option based on the stored value
const storedValue = localStorage.getItem(select.name);
if (storedValue) {
select.value = storedValue;
}
}
// Set the selected option image based on the selected value
const selectedOption = select.querySelector(`option[value="${select.value}"]`);
if (selectedOption) {
const image = selectedOption.getAttribute('data-image');
if (image) {
select.style.backgroundImage = `url(${image})`;
selectImage.src = image;
}
}
// Update the select element and image when the user makes a selection
select.addEventListener('change', () => {
const selectedOption = select.options[select.selectedIndex];
const image = selectedOption.getAttribute('data-image');
if (image) {
select.style.backgroundImage = `url(${image})`;
selectImage.src = image;
} else {
select.style.backgroundImage = '';
selectImage.src = '';
}
// Save the selected value to localStorage
localStorage.setItem(select.name, select.value);
});
// Hide the select icon and image on page load
selectIcon.style.display = 'none';
selectImage.style.display = 'none';
}
// Call the setupCustomSelect function for each custom select element
const customSelects = document.querySelectorAll('.custom-select select');
customSelects.forEach(select => {
setupCustomSelect(select);
});

File diff suppressed because one or more lines are too long

View File

@@ -1,614 +0,0 @@
/**
* @fileoverview
* - Using the 'QRCode for Javascript library'
* - Fixed dataset of 'QRCode for Javascript library' for support full-spec.
* - this library has no dependencies.
*
* @author davidshimjs
* @see <a href="http://www.d-project.com/" target="_blank">http://www.d-project.com/</a>
* @see <a href="http://jeromeetienne.github.com/jquery-qrcode/" target="_blank">http://jeromeetienne.github.com/jquery-qrcode/</a>
*/
var QRCode;
(function () {
//---------------------------------------------------------------------
// QRCode for JavaScript
//
// Copyright (c) 2009 Kazuhiko Arase
//
// URL: http://www.d-project.com/
//
// Licensed under the MIT license:
// http://www.opensource.org/licenses/mit-license.php
//
// The word "QR Code" is registered trademark of
// DENSO WAVE INCORPORATED
// http://www.denso-wave.com/qrcode/faqpatent-e.html
//
//---------------------------------------------------------------------
function QR8bitByte(data) {
this.mode = QRMode.MODE_8BIT_BYTE;
this.data = data;
this.parsedData = [];
// Added to support UTF-8 Characters
for (var i = 0, l = this.data.length; i < l; i++) {
var byteArray = [];
var code = this.data.charCodeAt(i);
if (code > 0x10000) {
byteArray[0] = 0xF0 | ((code & 0x1C0000) >>> 18);
byteArray[1] = 0x80 | ((code & 0x3F000) >>> 12);
byteArray[2] = 0x80 | ((code & 0xFC0) >>> 6);
byteArray[3] = 0x80 | (code & 0x3F);
} else if (code > 0x800) {
byteArray[0] = 0xE0 | ((code & 0xF000) >>> 12);
byteArray[1] = 0x80 | ((code & 0xFC0) >>> 6);
byteArray[2] = 0x80 | (code & 0x3F);
} else if (code > 0x80) {
byteArray[0] = 0xC0 | ((code & 0x7C0) >>> 6);
byteArray[1] = 0x80 | (code & 0x3F);
} else {
byteArray[0] = code;
}
this.parsedData.push(byteArray);
}
this.parsedData = Array.prototype.concat.apply([], this.parsedData);
if (this.parsedData.length != this.data.length) {
this.parsedData.unshift(191);
this.parsedData.unshift(187);
this.parsedData.unshift(239);
}
}
QR8bitByte.prototype = {
getLength: function (buffer) {
return this.parsedData.length;
},
write: function (buffer) {
for (var i = 0, l = this.parsedData.length; i < l; i++) {
buffer.put(this.parsedData[i], 8);
}
}
};
function QRCodeModel(typeNumber, errorCorrectLevel) {
this.typeNumber = typeNumber;
this.errorCorrectLevel = errorCorrectLevel;
this.modules = null;
this.moduleCount = 0;
this.dataCache = null;
this.dataList = [];
}
QRCodeModel.prototype={addData:function(data){var newData=new QR8bitByte(data);this.dataList.push(newData);this.dataCache=null;},isDark:function(row,col){if(row<0||this.moduleCount<=row||col<0||this.moduleCount<=col){throw new Error(row+","+col);}
return this.modules[row][col];},getModuleCount:function(){return this.moduleCount;},make:function(){this.makeImpl(false,this.getBestMaskPattern());},makeImpl:function(test,maskPattern){this.moduleCount=this.typeNumber*4+17;this.modules=new Array(this.moduleCount);for(var row=0;row<this.moduleCount;row++){this.modules[row]=new Array(this.moduleCount);for(var col=0;col<this.moduleCount;col++){this.modules[row][col]=null;}}
this.setupPositionProbePattern(0,0);this.setupPositionProbePattern(this.moduleCount-7,0);this.setupPositionProbePattern(0,this.moduleCount-7);this.setupPositionAdjustPattern();this.setupTimingPattern();this.setupTypeInfo(test,maskPattern);if(this.typeNumber>=7){this.setupTypeNumber(test);}
if(this.dataCache==null){this.dataCache=QRCodeModel.createData(this.typeNumber,this.errorCorrectLevel,this.dataList);}
this.mapData(this.dataCache,maskPattern);},setupPositionProbePattern:function(row,col){for(var r=-1;r<=7;r++){if(row+r<=-1||this.moduleCount<=row+r)continue;for(var c=-1;c<=7;c++){if(col+c<=-1||this.moduleCount<=col+c)continue;if((0<=r&&r<=6&&(c==0||c==6))||(0<=c&&c<=6&&(r==0||r==6))||(2<=r&&r<=4&&2<=c&&c<=4)){this.modules[row+r][col+c]=true;}else{this.modules[row+r][col+c]=false;}}}},getBestMaskPattern:function(){var minLostPoint=0;var pattern=0;for(var i=0;i<8;i++){this.makeImpl(true,i);var lostPoint=QRUtil.getLostPoint(this);if(i==0||minLostPoint>lostPoint){minLostPoint=lostPoint;pattern=i;}}
return pattern;},createMovieClip:function(target_mc,instance_name,depth){var qr_mc=target_mc.createEmptyMovieClip(instance_name,depth);var cs=1;this.make();for(var row=0;row<this.modules.length;row++){var y=row*cs;for(var col=0;col<this.modules[row].length;col++){var x=col*cs;var dark=this.modules[row][col];if(dark){qr_mc.beginFill(0,100);qr_mc.moveTo(x,y);qr_mc.lineTo(x+cs,y);qr_mc.lineTo(x+cs,y+cs);qr_mc.lineTo(x,y+cs);qr_mc.endFill();}}}
return qr_mc;},setupTimingPattern:function(){for(var r=8;r<this.moduleCount-8;r++){if(this.modules[r][6]!=null){continue;}
this.modules[r][6]=(r%2==0);}
for(var c=8;c<this.moduleCount-8;c++){if(this.modules[6][c]!=null){continue;}
this.modules[6][c]=(c%2==0);}},setupPositionAdjustPattern:function(){var pos=QRUtil.getPatternPosition(this.typeNumber);for(var i=0;i<pos.length;i++){for(var j=0;j<pos.length;j++){var row=pos[i];var col=pos[j];if(this.modules[row][col]!=null){continue;}
for(var r=-2;r<=2;r++){for(var c=-2;c<=2;c++){if(r==-2||r==2||c==-2||c==2||(r==0&&c==0)){this.modules[row+r][col+c]=true;}else{this.modules[row+r][col+c]=false;}}}}}},setupTypeNumber:function(test){var bits=QRUtil.getBCHTypeNumber(this.typeNumber);for(var i=0;i<18;i++){var mod=(!test&&((bits>>i)&1)==1);this.modules[Math.floor(i/3)][i%3+this.moduleCount-8-3]=mod;}
for(var i=0;i<18;i++){var mod=(!test&&((bits>>i)&1)==1);this.modules[i%3+this.moduleCount-8-3][Math.floor(i/3)]=mod;}},setupTypeInfo:function(test,maskPattern){var data=(this.errorCorrectLevel<<3)|maskPattern;var bits=QRUtil.getBCHTypeInfo(data);for(var i=0;i<15;i++){var mod=(!test&&((bits>>i)&1)==1);if(i<6){this.modules[i][8]=mod;}else if(i<8){this.modules[i+1][8]=mod;}else{this.modules[this.moduleCount-15+i][8]=mod;}}
for(var i=0;i<15;i++){var mod=(!test&&((bits>>i)&1)==1);if(i<8){this.modules[8][this.moduleCount-i-1]=mod;}else if(i<9){this.modules[8][15-i-1+1]=mod;}else{this.modules[8][15-i-1]=mod;}}
this.modules[this.moduleCount-8][8]=(!test);},mapData:function(data,maskPattern){var inc=-1;var row=this.moduleCount-1;var bitIndex=7;var byteIndex=0;for(var col=this.moduleCount-1;col>0;col-=2){if(col==6)col--;while(true){for(var c=0;c<2;c++){if(this.modules[row][col-c]==null){var dark=false;if(byteIndex<data.length){dark=(((data[byteIndex]>>>bitIndex)&1)==1);}
var mask=QRUtil.getMask(maskPattern,row,col-c);if(mask){dark=!dark;}
this.modules[row][col-c]=dark;bitIndex--;if(bitIndex==-1){byteIndex++;bitIndex=7;}}}
row+=inc;if(row<0||this.moduleCount<=row){row-=inc;inc=-inc;break;}}}}};QRCodeModel.PAD0=0xEC;QRCodeModel.PAD1=0x11;QRCodeModel.createData=function(typeNumber,errorCorrectLevel,dataList){var rsBlocks=QRRSBlock.getRSBlocks(typeNumber,errorCorrectLevel);var buffer=new QRBitBuffer();for(var i=0;i<dataList.length;i++){var data=dataList[i];buffer.put(data.mode,4);buffer.put(data.getLength(),QRUtil.getLengthInBits(data.mode,typeNumber));data.write(buffer);}
var totalDataCount=0;for(var i=0;i<rsBlocks.length;i++){totalDataCount+=rsBlocks[i].dataCount;}
if(buffer.getLengthInBits()>totalDataCount*8){throw new Error("code length overflow. ("
+buffer.getLengthInBits()
+">"
+totalDataCount*8
+")");}
if(buffer.getLengthInBits()+4<=totalDataCount*8){buffer.put(0,4);}
while(buffer.getLengthInBits()%8!=0){buffer.putBit(false);}
while(true){if(buffer.getLengthInBits()>=totalDataCount*8){break;}
buffer.put(QRCodeModel.PAD0,8);if(buffer.getLengthInBits()>=totalDataCount*8){break;}
buffer.put(QRCodeModel.PAD1,8);}
return QRCodeModel.createBytes(buffer,rsBlocks);};QRCodeModel.createBytes=function(buffer,rsBlocks){var offset=0;var maxDcCount=0;var maxEcCount=0;var dcdata=new Array(rsBlocks.length);var ecdata=new Array(rsBlocks.length);for(var r=0;r<rsBlocks.length;r++){var dcCount=rsBlocks[r].dataCount;var ecCount=rsBlocks[r].totalCount-dcCount;maxDcCount=Math.max(maxDcCount,dcCount);maxEcCount=Math.max(maxEcCount,ecCount);dcdata[r]=new Array(dcCount);for(var i=0;i<dcdata[r].length;i++){dcdata[r][i]=0xff&buffer.buffer[i+offset];}
offset+=dcCount;var rsPoly=QRUtil.getErrorCorrectPolynomial(ecCount);var rawPoly=new QRPolynomial(dcdata[r],rsPoly.getLength()-1);var modPoly=rawPoly.mod(rsPoly);ecdata[r]=new Array(rsPoly.getLength()-1);for(var i=0;i<ecdata[r].length;i++){var modIndex=i+modPoly.getLength()-ecdata[r].length;ecdata[r][i]=(modIndex>=0)?modPoly.get(modIndex):0;}}
var totalCodeCount=0;for(var i=0;i<rsBlocks.length;i++){totalCodeCount+=rsBlocks[i].totalCount;}
var data=new Array(totalCodeCount);var index=0;for(var i=0;i<maxDcCount;i++){for(var r=0;r<rsBlocks.length;r++){if(i<dcdata[r].length){data[index++]=dcdata[r][i];}}}
for(var i=0;i<maxEcCount;i++){for(var r=0;r<rsBlocks.length;r++){if(i<ecdata[r].length){data[index++]=ecdata[r][i];}}}
return data;};var QRMode={MODE_NUMBER:1<<0,MODE_ALPHA_NUM:1<<1,MODE_8BIT_BYTE:1<<2,MODE_KANJI:1<<3};var QRErrorCorrectLevel={L:1,M:0,Q:3,H:2};var QRMaskPattern={PATTERN000:0,PATTERN001:1,PATTERN010:2,PATTERN011:3,PATTERN100:4,PATTERN101:5,PATTERN110:6,PATTERN111:7};var QRUtil={PATTERN_POSITION_TABLE:[[],[6,18],[6,22],[6,26],[6,30],[6,34],[6,22,38],[6,24,42],[6,26,46],[6,28,50],[6,30,54],[6,32,58],[6,34,62],[6,26,46,66],[6,26,48,70],[6,26,50,74],[6,30,54,78],[6,30,56,82],[6,30,58,86],[6,34,62,90],[6,28,50,72,94],[6,26,50,74,98],[6,30,54,78,102],[6,28,54,80,106],[6,32,58,84,110],[6,30,58,86,114],[6,34,62,90,118],[6,26,50,74,98,122],[6,30,54,78,102,126],[6,26,52,78,104,130],[6,30,56,82,108,134],[6,34,60,86,112,138],[6,30,58,86,114,142],[6,34,62,90,118,146],[6,30,54,78,102,126,150],[6,24,50,76,102,128,154],[6,28,54,80,106,132,158],[6,32,58,84,110,136,162],[6,26,54,82,110,138,166],[6,30,58,86,114,142,170]],G15:(1<<10)|(1<<8)|(1<<5)|(1<<4)|(1<<2)|(1<<1)|(1<<0),G18:(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8)|(1<<5)|(1<<2)|(1<<0),G15_MASK:(1<<14)|(1<<12)|(1<<10)|(1<<4)|(1<<1),getBCHTypeInfo:function(data){var d=data<<10;while(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G15)>=0){d^=(QRUtil.G15<<(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G15)));}
return((data<<10)|d)^QRUtil.G15_MASK;},getBCHTypeNumber:function(data){var d=data<<12;while(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G18)>=0){d^=(QRUtil.G18<<(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G18)));}
return(data<<12)|d;},getBCHDigit:function(data){var digit=0;while(data!=0){digit++;data>>>=1;}
return digit;},getPatternPosition:function(typeNumber){return QRUtil.PATTERN_POSITION_TABLE[typeNumber-1];},getMask:function(maskPattern,i,j){switch(maskPattern){case QRMaskPattern.PATTERN000:return(i+j)%2==0;case QRMaskPattern.PATTERN001:return i%2==0;case QRMaskPattern.PATTERN010:return j%3==0;case QRMaskPattern.PATTERN011:return(i+j)%3==0;case QRMaskPattern.PATTERN100:return(Math.floor(i/2)+Math.floor(j/3))%2==0;case QRMaskPattern.PATTERN101:return(i*j)%2+(i*j)%3==0;case QRMaskPattern.PATTERN110:return((i*j)%2+(i*j)%3)%2==0;case QRMaskPattern.PATTERN111:return((i*j)%3+(i+j)%2)%2==0;default:throw new Error("bad maskPattern:"+maskPattern);}},getErrorCorrectPolynomial:function(errorCorrectLength){var a=new QRPolynomial([1],0);for(var i=0;i<errorCorrectLength;i++){a=a.multiply(new QRPolynomial([1,QRMath.gexp(i)],0));}
return a;},getLengthInBits:function(mode,type){if(1<=type&&type<10){switch(mode){case QRMode.MODE_NUMBER:return 10;case QRMode.MODE_ALPHA_NUM:return 9;case QRMode.MODE_8BIT_BYTE:return 8;case QRMode.MODE_KANJI:return 8;default:throw new Error("mode:"+mode);}}else if(type<27){switch(mode){case QRMode.MODE_NUMBER:return 12;case QRMode.MODE_ALPHA_NUM:return 11;case QRMode.MODE_8BIT_BYTE:return 16;case QRMode.MODE_KANJI:return 10;default:throw new Error("mode:"+mode);}}else if(type<41){switch(mode){case QRMode.MODE_NUMBER:return 14;case QRMode.MODE_ALPHA_NUM:return 13;case QRMode.MODE_8BIT_BYTE:return 16;case QRMode.MODE_KANJI:return 12;default:throw new Error("mode:"+mode);}}else{throw new Error("type:"+type);}},getLostPoint:function(qrCode){var moduleCount=qrCode.getModuleCount();var lostPoint=0;for(var row=0;row<moduleCount;row++){for(var col=0;col<moduleCount;col++){var sameCount=0;var dark=qrCode.isDark(row,col);for(var r=-1;r<=1;r++){if(row+r<0||moduleCount<=row+r){continue;}
for(var c=-1;c<=1;c++){if(col+c<0||moduleCount<=col+c){continue;}
if(r==0&&c==0){continue;}
if(dark==qrCode.isDark(row+r,col+c)){sameCount++;}}}
if(sameCount>5){lostPoint+=(3+sameCount-5);}}}
for(var row=0;row<moduleCount-1;row++){for(var col=0;col<moduleCount-1;col++){var count=0;if(qrCode.isDark(row,col))count++;if(qrCode.isDark(row+1,col))count++;if(qrCode.isDark(row,col+1))count++;if(qrCode.isDark(row+1,col+1))count++;if(count==0||count==4){lostPoint+=3;}}}
for(var row=0;row<moduleCount;row++){for(var col=0;col<moduleCount-6;col++){if(qrCode.isDark(row,col)&&!qrCode.isDark(row,col+1)&&qrCode.isDark(row,col+2)&&qrCode.isDark(row,col+3)&&qrCode.isDark(row,col+4)&&!qrCode.isDark(row,col+5)&&qrCode.isDark(row,col+6)){lostPoint+=40;}}}
for(var col=0;col<moduleCount;col++){for(var row=0;row<moduleCount-6;row++){if(qrCode.isDark(row,col)&&!qrCode.isDark(row+1,col)&&qrCode.isDark(row+2,col)&&qrCode.isDark(row+3,col)&&qrCode.isDark(row+4,col)&&!qrCode.isDark(row+5,col)&&qrCode.isDark(row+6,col)){lostPoint+=40;}}}
var darkCount=0;for(var col=0;col<moduleCount;col++){for(var row=0;row<moduleCount;row++){if(qrCode.isDark(row,col)){darkCount++;}}}
var ratio=Math.abs(100*darkCount/moduleCount/moduleCount-50)/5;lostPoint+=ratio*10;return lostPoint;}};var QRMath={glog:function(n){if(n<1){throw new Error("glog("+n+")");}
return QRMath.LOG_TABLE[n];},gexp:function(n){while(n<0){n+=255;}
while(n>=256){n-=255;}
return QRMath.EXP_TABLE[n];},EXP_TABLE:new Array(256),LOG_TABLE:new Array(256)};for(var i=0;i<8;i++){QRMath.EXP_TABLE[i]=1<<i;}
for(var i=8;i<256;i++){QRMath.EXP_TABLE[i]=QRMath.EXP_TABLE[i-4]^QRMath.EXP_TABLE[i-5]^QRMath.EXP_TABLE[i-6]^QRMath.EXP_TABLE[i-8];}
for(var i=0;i<255;i++){QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]]=i;}
function QRPolynomial(num,shift){if(num.length==undefined){throw new Error(num.length+"/"+shift);}
var offset=0;while(offset<num.length&&num[offset]==0){offset++;}
this.num=new Array(num.length-offset+shift);for(var i=0;i<num.length-offset;i++){this.num[i]=num[i+offset];}}
QRPolynomial.prototype={get:function(index){return this.num[index];},getLength:function(){return this.num.length;},multiply:function(e){var num=new Array(this.getLength()+e.getLength()-1);for(var i=0;i<this.getLength();i++){for(var j=0;j<e.getLength();j++){num[i+j]^=QRMath.gexp(QRMath.glog(this.get(i))+QRMath.glog(e.get(j)));}}
return new QRPolynomial(num,0);},mod:function(e){if(this.getLength()-e.getLength()<0){return this;}
var ratio=QRMath.glog(this.get(0))-QRMath.glog(e.get(0));var num=new Array(this.getLength());for(var i=0;i<this.getLength();i++){num[i]=this.get(i);}
for(var i=0;i<e.getLength();i++){num[i]^=QRMath.gexp(QRMath.glog(e.get(i))+ratio);}
return new QRPolynomial(num,0).mod(e);}};function QRRSBlock(totalCount,dataCount){this.totalCount=totalCount;this.dataCount=dataCount;}
QRRSBlock.RS_BLOCK_TABLE=[[1,26,19],[1,26,16],[1,26,13],[1,26,9],[1,44,34],[1,44,28],[1,44,22],[1,44,16],[1,70,55],[1,70,44],[2,35,17],[2,35,13],[1,100,80],[2,50,32],[2,50,24],[4,25,9],[1,134,108],[2,67,43],[2,33,15,2,34,16],[2,33,11,2,34,12],[2,86,68],[4,43,27],[4,43,19],[4,43,15],[2,98,78],[4,49,31],[2,32,14,4,33,15],[4,39,13,1,40,14],[2,121,97],[2,60,38,2,61,39],[4,40,18,2,41,19],[4,40,14,2,41,15],[2,146,116],[3,58,36,2,59,37],[4,36,16,4,37,17],[4,36,12,4,37,13],[2,86,68,2,87,69],[4,69,43,1,70,44],[6,43,19,2,44,20],[6,43,15,2,44,16],[4,101,81],[1,80,50,4,81,51],[4,50,22,4,51,23],[3,36,12,8,37,13],[2,116,92,2,117,93],[6,58,36,2,59,37],[4,46,20,6,47,21],[7,42,14,4,43,15],[4,133,107],[8,59,37,1,60,38],[8,44,20,4,45,21],[12,33,11,4,34,12],[3,145,115,1,146,116],[4,64,40,5,65,41],[11,36,16,5,37,17],[11,36,12,5,37,13],[5,109,87,1,110,88],[5,65,41,5,66,42],[5,54,24,7,55,25],[11,36,12],[5,122,98,1,123,99],[7,73,45,3,74,46],[15,43,19,2,44,20],[3,45,15,13,46,16],[1,135,107,5,136,108],[10,74,46,1,75,47],[1,50,22,15,51,23],[2,42,14,17,43,15],[5,150,120,1,151,121],[9,69,43,4,70,44],[17,50,22,1,51,23],[2,42,14,19,43,15],[3,141,113,4,142,114],[3,70,44,11,71,45],[17,47,21,4,48,22],[9,39,13,16,40,14],[3,135,107,5,136,108],[3,67,41,13,68,42],[15,54,24,5,55,25],[15,43,15,10,44,16],[4,144,116,4,145,117],[17,68,42],[17,50,22,6,51,23],[19,46,16,6,47,17],[2,139,111,7,140,112],[17,74,46],[7,54,24,16,55,25],[34,37,13],[4,151,121,5,152,122],[4,75,47,14,76,48],[11,54,24,14,55,25],[16,45,15,14,46,16],[6,147,117,4,148,118],[6,73,45,14,74,46],[11,54,24,16,55,25],[30,46,16,2,47,17],[8,132,106,4,133,107],[8,75,47,13,76,48],[7,54,24,22,55,25],[22,45,15,13,46,16],[10,142,114,2,143,115],[19,74,46,4,75,47],[28,50,22,6,51,23],[33,46,16,4,47,17],[8,152,122,4,153,123],[22,73,45,3,74,46],[8,53,23,26,54,24],[12,45,15,28,46,16],[3,147,117,10,148,118],[3,73,45,23,74,46],[4,54,24,31,55,25],[11,45,15,31,46,16],[7,146,116,7,147,117],[21,73,45,7,74,46],[1,53,23,37,54,24],[19,45,15,26,46,16],[5,145,115,10,146,116],[19,75,47,10,76,48],[15,54,24,25,55,25],[23,45,15,25,46,16],[13,145,115,3,146,116],[2,74,46,29,75,47],[42,54,24,1,55,25],[23,45,15,28,46,16],[17,145,115],[10,74,46,23,75,47],[10,54,24,35,55,25],[19,45,15,35,46,16],[17,145,115,1,146,116],[14,74,46,21,75,47],[29,54,24,19,55,25],[11,45,15,46,46,16],[13,145,115,6,146,116],[14,74,46,23,75,47],[44,54,24,7,55,25],[59,46,16,1,47,17],[12,151,121,7,152,122],[12,75,47,26,76,48],[39,54,24,14,55,25],[22,45,15,41,46,16],[6,151,121,14,152,122],[6,75,47,34,76,48],[46,54,24,10,55,25],[2,45,15,64,46,16],[17,152,122,4,153,123],[29,74,46,14,75,47],[49,54,24,10,55,25],[24,45,15,46,46,16],[4,152,122,18,153,123],[13,74,46,32,75,47],[48,54,24,14,55,25],[42,45,15,32,46,16],[20,147,117,4,148,118],[40,75,47,7,76,48],[43,54,24,22,55,25],[10,45,15,67,46,16],[19,148,118,6,149,119],[18,75,47,31,76,48],[34,54,24,34,55,25],[20,45,15,61,46,16]];QRRSBlock.getRSBlocks=function(typeNumber,errorCorrectLevel){var rsBlock=QRRSBlock.getRsBlockTable(typeNumber,errorCorrectLevel);if(rsBlock==undefined){throw new Error("bad rs block @ typeNumber:"+typeNumber+"/errorCorrectLevel:"+errorCorrectLevel);}
var length=rsBlock.length/3;var list=[];for(var i=0;i<length;i++){var count=rsBlock[i*3+0];var totalCount=rsBlock[i*3+1];var dataCount=rsBlock[i*3+2];for(var j=0;j<count;j++){list.push(new QRRSBlock(totalCount,dataCount));}}
return list;};QRRSBlock.getRsBlockTable=function(typeNumber,errorCorrectLevel){switch(errorCorrectLevel){case QRErrorCorrectLevel.L:return QRRSBlock.RS_BLOCK_TABLE[(typeNumber-1)*4+0];case QRErrorCorrectLevel.M:return QRRSBlock.RS_BLOCK_TABLE[(typeNumber-1)*4+1];case QRErrorCorrectLevel.Q:return QRRSBlock.RS_BLOCK_TABLE[(typeNumber-1)*4+2];case QRErrorCorrectLevel.H:return QRRSBlock.RS_BLOCK_TABLE[(typeNumber-1)*4+3];default:return undefined;}};function QRBitBuffer(){this.buffer=[];this.length=0;}
QRBitBuffer.prototype={get:function(index){var bufIndex=Math.floor(index/8);return((this.buffer[bufIndex]>>>(7-index%8))&1)==1;},put:function(num,length){for(var i=0;i<length;i++){this.putBit(((num>>>(length-i-1))&1)==1);}},getLengthInBits:function(){return this.length;},putBit:function(bit){var bufIndex=Math.floor(this.length/8);if(this.buffer.length<=bufIndex){this.buffer.push(0);}
if(bit){this.buffer[bufIndex]|=(0x80>>>(this.length%8));}
this.length++;}};var QRCodeLimitLength=[[17,14,11,7],[32,26,20,14],[53,42,32,24],[78,62,46,34],[106,84,60,44],[134,106,74,58],[154,122,86,64],[192,152,108,84],[230,180,130,98],[271,213,151,119],[321,251,177,137],[367,287,203,155],[425,331,241,177],[458,362,258,194],[520,412,292,220],[586,450,322,250],[644,504,364,280],[718,560,394,310],[792,624,442,338],[858,666,482,382],[929,711,509,403],[1003,779,565,439],[1091,857,611,461],[1171,911,661,511],[1273,997,715,535],[1367,1059,751,593],[1465,1125,805,625],[1528,1190,868,658],[1628,1264,908,698],[1732,1370,982,742],[1840,1452,1030,790],[1952,1538,1112,842],[2068,1628,1168,898],[2188,1722,1228,958],[2303,1809,1283,983],[2431,1911,1351,1051],[2563,1989,1423,1093],[2699,2099,1499,1139],[2809,2213,1579,1219],[2953,2331,1663,1273]];
function _isSupportCanvas() {
return typeof CanvasRenderingContext2D != "undefined";
}
// android 2.x doesn't support Data-URI spec
function _getAndroid() {
var android = false;
var sAgent = navigator.userAgent;
if (/android/i.test(sAgent)) { // android
android = true;
var aMat = sAgent.toString().match(/android ([0-9]\.[0-9])/i);
if (aMat && aMat[1]) {
android = parseFloat(aMat[1]);
}
}
return android;
}
var svgDrawer = (function() {
var Drawing = function (el, htOption) {
this._el = el;
this._htOption = htOption;
};
Drawing.prototype.draw = function (oQRCode) {
var _htOption = this._htOption;
var _el = this._el;
var nCount = oQRCode.getModuleCount();
var nWidth = Math.floor(_htOption.width / nCount);
var nHeight = Math.floor(_htOption.height / nCount);
this.clear();
function makeSVG(tag, attrs) {
var el = document.createElementNS('http://www.w3.org/2000/svg', tag);
for (var k in attrs)
if (attrs.hasOwnProperty(k)) el.setAttribute(k, attrs[k]);
return el;
}
var svg = makeSVG("svg" , {'viewBox': '0 0 ' + String(nCount) + " " + String(nCount), 'width': '100%', 'height': '100%', 'fill': _htOption.colorLight});
svg.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink", "http://www.w3.org/1999/xlink");
_el.appendChild(svg);
svg.appendChild(makeSVG("rect", {"fill": _htOption.colorLight, "width": "100%", "height": "100%"}));
svg.appendChild(makeSVG("rect", {"fill": _htOption.colorDark, "width": "1", "height": "1", "id": "template"}));
for (var row = 0; row < nCount; row++) {
for (var col = 0; col < nCount; col++) {
if (oQRCode.isDark(row, col)) {
var child = makeSVG("use", {"x": String(row), "y": String(col)});
child.setAttributeNS("http://www.w3.org/1999/xlink", "href", "#template")
svg.appendChild(child);
}
}
}
};
Drawing.prototype.clear = function () {
while (this._el.hasChildNodes())
this._el.removeChild(this._el.lastChild);
};
return Drawing;
})();
var useSVG = document.documentElement.tagName.toLowerCase() === "svg";
// Drawing in DOM by using Table tag
var Drawing = useSVG ? svgDrawer : !_isSupportCanvas() ? (function () {
var Drawing = function (el, htOption) {
this._el = el;
this._htOption = htOption;
};
/**
* Draw the QRCode
*
* @param {QRCode} oQRCode
*/
Drawing.prototype.draw = function (oQRCode) {
var _htOption = this._htOption;
var _el = this._el;
var nCount = oQRCode.getModuleCount();
var nWidth = Math.floor(_htOption.width / nCount);
var nHeight = Math.floor(_htOption.height / nCount);
var aHTML = ['<table style="border:0;border-collapse:collapse;">'];
for (var row = 0; row < nCount; row++) {
aHTML.push('<tr>');
for (var col = 0; col < nCount; col++) {
aHTML.push('<td style="border:0;border-collapse:collapse;padding:0;margin:0;width:' + nWidth + 'px;height:' + nHeight + 'px;background-color:' + (oQRCode.isDark(row, col) ? _htOption.colorDark : _htOption.colorLight) + ';"></td>');
}
aHTML.push('</tr>');
}
aHTML.push('</table>');
_el.innerHTML = aHTML.join('');
// Fix the margin values as real size.
var elTable = _el.childNodes[0];
var nLeftMarginTable = (_htOption.width - elTable.offsetWidth) / 2;
var nTopMarginTable = (_htOption.height - elTable.offsetHeight) / 2;
if (nLeftMarginTable > 0 && nTopMarginTable > 0) {
elTable.style.margin = nTopMarginTable + "px " + nLeftMarginTable + "px";
}
};
/**
* Clear the QRCode
*/
Drawing.prototype.clear = function () {
this._el.innerHTML = '';
};
return Drawing;
})() : (function () { // Drawing in Canvas
function _onMakeImage() {
this._elImage.src = this._elCanvas.toDataURL("image/png");
this._elImage.style.display = "block";
this._elCanvas.style.display = "none";
}
// Android 2.1 bug workaround
// http://code.google.com/p/android/issues/detail?id=5141
if (this._android && this._android <= 2.1) {
var factor = 1 / window.devicePixelRatio;
var drawImage = CanvasRenderingContext2D.prototype.drawImage;
CanvasRenderingContext2D.prototype.drawImage = function (image, sx, sy, sw, sh, dx, dy, dw, dh) {
if (("nodeName" in image) && /img/i.test(image.nodeName)) {
for (var i = arguments.length - 1; i >= 1; i--) {
arguments[i] = arguments[i] * factor;
}
} else if (typeof dw == "undefined") {
arguments[1] *= factor;
arguments[2] *= factor;
arguments[3] *= factor;
arguments[4] *= factor;
}
drawImage.apply(this, arguments);
};
}
/**
* Check whether the user's browser supports Data URI or not
*
* @private
* @param {Function} fSuccess Occurs if it supports Data URI
* @param {Function} fFail Occurs if it doesn't support Data URI
*/
function _safeSetDataURI(fSuccess, fFail) {
var self = this;
self._fFail = fFail;
self._fSuccess = fSuccess;
// Check it just once
if (self._bSupportDataURI === null) {
var el = document.createElement("img");
var fOnError = function() {
self._bSupportDataURI = false;
if (self._fFail) {
self._fFail.call(self);
}
};
var fOnSuccess = function() {
self._bSupportDataURI = true;
if (self._fSuccess) {
self._fSuccess.call(self);
}
};
el.onabort = fOnError;
el.onerror = fOnError;
el.onload = fOnSuccess;
el.src = "data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="; // the Image contains 1px data.
return;
} else if (self._bSupportDataURI === true && self._fSuccess) {
self._fSuccess.call(self);
} else if (self._bSupportDataURI === false && self._fFail) {
self._fFail.call(self);
}
};
/**
* Drawing QRCode by using canvas
*
* @constructor
* @param {HTMLElement} el
* @param {Object} htOption QRCode Options
*/
var Drawing = function (el, htOption) {
this._bIsPainted = false;
this._android = _getAndroid();
this._htOption = htOption;
this._elCanvas = document.createElement("canvas");
this._elCanvas.width = htOption.width;
this._elCanvas.height = htOption.height;
el.appendChild(this._elCanvas);
this._el = el;
this._oContext = this._elCanvas.getContext("2d");
this._bIsPainted = false;
this._elImage = document.createElement("img");
this._elImage.alt = "Scan me!";
this._elImage.style.display = "none";
this._el.appendChild(this._elImage);
this._bSupportDataURI = null;
};
/**
* Draw the QRCode
*
* @param {QRCode} oQRCode
*/
Drawing.prototype.draw = function (oQRCode) {
var _elImage = this._elImage;
var _oContext = this._oContext;
var _htOption = this._htOption;
var nCount = oQRCode.getModuleCount();
var nWidth = _htOption.width / nCount;
var nHeight = _htOption.height / nCount;
var nRoundedWidth = Math.round(nWidth);
var nRoundedHeight = Math.round(nHeight);
_elImage.style.display = "none";
this.clear();
for (var row = 0; row < nCount; row++) {
for (var col = 0; col < nCount; col++) {
var bIsDark = oQRCode.isDark(row, col);
var nLeft = col * nWidth;
var nTop = row * nHeight;
_oContext.strokeStyle = bIsDark ? _htOption.colorDark : _htOption.colorLight;
_oContext.lineWidth = 1;
_oContext.fillStyle = bIsDark ? _htOption.colorDark : _htOption.colorLight;
_oContext.fillRect(nLeft, nTop, nWidth, nHeight);
// 안티 앨리어싱 방지 처리
_oContext.strokeRect(
Math.floor(nLeft) + 0.5,
Math.floor(nTop) + 0.5,
nRoundedWidth,
nRoundedHeight
);
_oContext.strokeRect(
Math.ceil(nLeft) - 0.5,
Math.ceil(nTop) - 0.5,
nRoundedWidth,
nRoundedHeight
);
}
}
this._bIsPainted = true;
};
/**
* Make the image from Canvas if the browser supports Data URI.
*/
Drawing.prototype.makeImage = function () {
if (this._bIsPainted) {
_safeSetDataURI.call(this, _onMakeImage);
}
};
/**
* Return whether the QRCode is painted or not
*
* @return {Boolean}
*/
Drawing.prototype.isPainted = function () {
return this._bIsPainted;
};
/**
* Clear the QRCode
*/
Drawing.prototype.clear = function () {
this._oContext.clearRect(0, 0, this._elCanvas.width, this._elCanvas.height);
this._bIsPainted = false;
};
/**
* @private
* @param {Number} nNumber
*/
Drawing.prototype.round = function (nNumber) {
if (!nNumber) {
return nNumber;
}
return Math.floor(nNumber * 1000) / 1000;
};
return Drawing;
})();
/**
* Get the type by string length
*
* @private
* @param {String} sText
* @param {Number} nCorrectLevel
* @return {Number} type
*/
function _getTypeNumber(sText, nCorrectLevel) {
var nType = 1;
var length = _getUTF8Length(sText);
for (var i = 0, len = QRCodeLimitLength.length; i <= len; i++) {
var nLimit = 0;
switch (nCorrectLevel) {
case QRErrorCorrectLevel.L :
nLimit = QRCodeLimitLength[i][0];
break;
case QRErrorCorrectLevel.M :
nLimit = QRCodeLimitLength[i][1];
break;
case QRErrorCorrectLevel.Q :
nLimit = QRCodeLimitLength[i][2];
break;
case QRErrorCorrectLevel.H :
nLimit = QRCodeLimitLength[i][3];
break;
}
if (length <= nLimit) {
break;
} else {
nType++;
}
}
if (nType > QRCodeLimitLength.length) {
throw new Error("Too long data");
}
return nType;
}
function _getUTF8Length(sText) {
var replacedText = encodeURI(sText).toString().replace(/\%[0-9a-fA-F]{2}/g, 'a');
return replacedText.length + (replacedText.length != sText ? 3 : 0);
}
/**
* @class QRCode
* @constructor
* @example
* new QRCode(document.getElementById("test"), "http://jindo.dev.naver.com/collie");
*
* @example
* var oQRCode = new QRCode("test", {
* text : "http://naver.com",
* width : 128,
* height : 128
* });
*
* oQRCode.clear(); // Clear the QRCode.
* oQRCode.makeCode("http://map.naver.com"); // Re-create the QRCode.
*
* @param {HTMLElement|String} el target element or 'id' attribute of element.
* @param {Object|String} vOption
* @param {String} vOption.text QRCode link data
* @param {Number} [vOption.width=256]
* @param {Number} [vOption.height=256]
* @param {String} [vOption.colorDark="#000000"]
* @param {String} [vOption.colorLight="#ffffff"]
* @param {QRCode.CorrectLevel} [vOption.correctLevel=QRCode.CorrectLevel.H] [L|M|Q|H]
*/
QRCode = function (el, vOption) {
this._htOption = {
width : 256,
height : 256,
typeNumber : 4,
colorDark : "#000000",
colorLight : "#ffffff",
correctLevel : QRErrorCorrectLevel.H
};
if (typeof vOption === 'string') {
vOption = {
text : vOption
};
}
// Overwrites options
if (vOption) {
for (var i in vOption) {
this._htOption[i] = vOption[i];
}
}
if (typeof el == "string") {
el = document.getElementById(el);
}
if (this._htOption.useSVG) {
Drawing = svgDrawer;
}
this._android = _getAndroid();
this._el = el;
this._oQRCode = null;
this._oDrawing = new Drawing(this._el, this._htOption);
if (this._htOption.text) {
this.makeCode(this._htOption.text);
}
};
/**
* Make the QRCode
*
* @param {String} sText link data
*/
QRCode.prototype.makeCode = function (sText) {
this._oQRCode = new QRCodeModel(_getTypeNumber(sText, this._htOption.correctLevel), this._htOption.correctLevel);
this._oQRCode.addData(sText);
this._oQRCode.make();
this._el.title = sText;
this._oDrawing.draw(this._oQRCode);
this.makeImage();
};
/**
* Make the Image from Canvas element
* - It occurs automatically
* - Android below 3 doesn't support Data-URI spec.
*
* @private
*/
QRCode.prototype.makeImage = function () {
if (typeof this._oDrawing.makeImage == "function" && (!this._android || this._android >= 3)) {
this._oDrawing.makeImage();
}
};
/**
* Clear the QRCode
*/
QRCode.prototype.clear = function () {
this._oDrawing.clear();
};
/**
* @name QRCode.CorrectLevel
*/
QRCode.CorrectLevel = QRErrorCorrectLevel;
})();

View File

@@ -38,22 +38,3 @@ window.addEventListener('DOMContentLoaded', (event) => {
}); });
}); });
}); });
const selects = document.querySelectorAll('select.disabled-select');
for (const select of selects) {
if (select.disabled) {
select.classList.add('disabled-select-enabled');
} else {
select.classList.remove('disabled-select-enabled');
}
}
const inputs = document.querySelectorAll('input.disabled-input, input[type="checkbox"].disabled-input');
for (const input of inputs) {
if (input.readOnly) {
input.classList.add('disabled-input-enabled');
} else {
input.classList.remove('disabled-input-enabled');
}
}

View File

@@ -1,5 +1,4 @@
{% include 'header.html' %} {% include 'header.html' %}
{% from 'style.html' import breadcrumb_line_svg %}
<div class="container mx-auto"> <div class="container mx-auto">
<section class="p-5 mt-5"> <section class="p-5 mt-5">
<div class="flex flex-wrap items-center -m-2"> <div class="flex flex-wrap items-center -m-2">
@@ -10,11 +9,19 @@
<p>Home</p> <p>Home</p>
</a> </a>
</li> </li>
<li>{{ breadcrumb_line_svg | safe }}</li> <li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
<li> <li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/404">404</a> <a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/404">404</a>
</li> </li>
<li>{{ breadcrumb_line_svg | safe }}</li> <li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
</ul> </ul>
</div> </div>
</div> </div>
@@ -30,6 +37,7 @@
<div class="flex flex-wrap"> <div class="flex flex-wrap">
<div class="w-full lg:w-auto py-1 lg:py-0 lg:mr-6"><a class="inline-block py-5 px-7 w-full text-base md:text-lg leading-4 text-blue-50 font-medium text-center bg-blue-500 hover:bg-blue-600 border border-blue-500 rounded-md shadow-sm focus:ring-0 focus:outline-none" href="/">Go Back</a></div> <div class="w-full lg:w-auto py-1 lg:py-0 lg:mr-6"><a class="inline-block py-5 px-7 w-full text-base md:text-lg leading-4 text-blue-50 font-medium text-center bg-blue-500 hover:bg-blue-600 border border-blue-500 rounded-md shadow-sm focus:ring-0 focus:outline-none" href="/">Go Back</a></div>
<div class="w-full lg:w-auto py-1 lg:py-0"><a class="inline-block py-5 px-7 w-full text-base md:text-lg leading-4 text-coolGray-800 font-medium text-center bg-white hover:bg-coolGray-100 border border-coolGray-200 rounded-md shadow-sm focus:ring-0 focus:outline-none" href="/refresh">Try Again</a></div> <div class="w-full lg:w-auto py-1 lg:py-0"><a class="inline-block py-5 px-7 w-full text-base md:text-lg leading-4 text-coolGray-800 font-medium text-center bg-white hover:bg-coolGray-100 border border-coolGray-200 rounded-md shadow-sm focus:ring-0 focus:outline-none" href="/refresh">Try Again</a></div>
<!-- todo add last URL page visit -->
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,5 +1,4 @@
{% include 'header.html' %} {% include 'header.html' %}
{% from 'style.html' import breadcrumb_line_svg, circular_arrows_svg %}
<div class="container mx-auto"> <div class="container mx-auto">
<section class="p-5 mt-5"> <section class="p-5 mt-5">
<div class="flex flex-wrap items-center -m-2"> <div class="flex flex-wrap items-center -m-2">
@@ -10,11 +9,19 @@
<p>Home</p> <p>Home</p>
</a> </a>
</li> </li>
<li>{{ breadcrumb_line_svg | safe }}</li> <li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
<li> <li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/active">Swaps In Progress</a> <a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/active">Swaps In Progress</a>
</li> </li>
<li>{{ breadcrumb_line_svg | safe }}</li> <li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
</ul> </ul>
</div> </div>
</div> </div>
@@ -32,13 +39,23 @@
</div> </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"> <div class="w-full md:w-1/2 p-3 p-6 container flex flex-wrap items-center justify-end items-center mx-auto">
{% if refresh %} {% if refresh %}
<a id="refresh" href="/active" class="rounded-full 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"> <a id="refresh" href="/active" class="flex flex-wrap justify-center px-5 py-4 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white borderdark:text-white dark:hover:text-white dark:bg-gray-600 dark:hover:bg-gray-700 dark:border-gray-600 dark:hover:border-gray-600 border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none">
{{ circular_arrows_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g fill="#ffffff">
<path fill="#ffffff" d="M12,3c1.989,0,3.873,0.65,5.43,1.833l-3.604,3.393l9.167,0.983L22.562,0l-3.655,3.442 C16.957,1.862,14.545,1,12,1C5.935,1,1,5.935,1,12h2C3,7.037,7.037,3,12,3z"></path>
<path data-color="color-2" d="M12,21c-1.989,0-3.873-0.65-5.43-1.833l3.604-3.393l-9.167-0.983L1.438,24l3.655-3.442 C7.043,22.138,9.455,23,12,23c6.065,0,11-4.935,11-11h-2C21,16.963,16.963,21,12,21z"></path>
</g>
</svg>
<span>Refresh 30 seconds</span> <span>Refresh 30 seconds</span>
</a> </a>
{% else %} {% else %}
<a id="refresh" href="/active" class="flex flex-wrap justify-center px-5 py-4 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white borderdark:text-white dark:hover:text-white dark:bg-gray-600 dark:hover:bg-gray-700 dark:border-gray-600 dark:hover:border-gray-600 border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none"> <a id="refresh" href="/active" class="flex flex-wrap justify-center px-5 py-4 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white borderdark:text-white dark:hover:text-white dark:bg-gray-600 dark:hover:bg-gray-700 dark:border-gray-600 dark:hover:border-gray-600 border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none">
{{ circular_arrows_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g fill="#ffffff">
<path fill="#ffffff" d="M12,3c1.989,0,3.873,0.65,5.43,1.833l-3.604,3.393l9.167,0.983L22.562,0l-3.655,3.442 C16.957,1.862,14.545,1,12,1C5.935,1,1,5.935,1,12h2C3,7.037,7.037,3,12,3z"></path>
<path data-color="color-2" d="M12,21c-1.989,0-3.873-0.65-5.43-1.833l3.604-3.393l-9.167-0.983L1.438,24l3.655-3.442 C7.043,22.138,9.455,23,12,23c6.065,0,11-4.935,11-11h-2C21,16.963,16.963,21,12,21z"></path>
</g>
</svg>
<span>Refresh</span> <span>Refresh</span>
</a> </a>
{% endif %} {% endif %}
@@ -66,22 +83,22 @@
</th> </th>
<th class="p-0"> <th class="p-0">
<div class="py-3 px-6 bg-coolGray-200 dark:bg-gray-600"> <div class="py-3 px-6 bg-coolGray-200 dark:bg-gray-600">
<span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">Offer ID</span> <span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">Offer ID </span>
</div> </div>
</th> </th>
<th class="p-0"> <th class="p-0">
<div class="py-3 px-6 bg-coolGray-200 dark:bg-gray-600"> <div class="py-3 px-6 bg-coolGray-200 dark:bg-gray-600">
<span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">Bid Status</span> <span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">Bid Status </span>
</div> </div>
</th> </th>
<th class="p-0"> <th class="p-0">
<div class="py-3 px-6 bg-coolGray-200 dark:bg-gray-600"> <div class="py-3 px-6 bg-coolGray-200 dark:bg-gray-600">
<span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">ITX Status</span> <span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">ITX Status </span>
</div> </div>
</th> </th>
<th class="p-0"> <th class="p-0">
<div class="py-3 px-6 rounded-tr-xl bg-coolGray-200 dark:bg-gray-600"> <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">PTX Status</span> <span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">PTX Status </span>
</div> </div>
</th> </th>
</tr> </tr>

View File

@@ -1,5 +1,4 @@
{% include 'header.html' %} {% include 'header.html' %}
{% from 'style.html' import breadcrumb_line_svg, white_automation_svg, page_forwards_svg, page_back_svg, filter_apply_svg %}
<div class="container mx-auto"> <div class="container mx-auto">
<section class="p-5 mt-5"> <section class="p-5 mt-5">
<div class="flex flex-wrap items-center -m-2"> <div class="flex flex-wrap items-center -m-2">
@@ -9,11 +8,19 @@
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/"> <a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/">
<p>Home</p> <p>Home</p>
</a> </a>
<li>{{ breadcrumb_line_svg | safe }}</li> <li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
<li> <li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/automation">Automation Strategies</a> <a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/automation">Automation Strategies</a>
</li> </li>
<li>{{ breadcrumb_line_svg | safe }}</li> <li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
</ul> </ul>
</ul> </ul>
</div> </div>
@@ -27,11 +34,25 @@
<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=""> <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="">
<div class="relative z-20 flex flex-wrap items-center -m-3"> <div class="relative z-20 flex flex-wrap items-center -m-3">
<div class="w-full md:w-1/2 p-3"> <div class="w-full md:w-1/2 p-3">
<h2 class="text-4xl font-bold text-white tracking-tighter">Automation Strategies</h2> <h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">Automation Strategies</h2>
<p class="font-normal text-coolGray-200 dark:text-white"></p>
</div> </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"> <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 href="/newautomationstrategy" class="rounded-full 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"> <a href="/newautomationstrategy" class="flex flex-wrap justify-center px-5 py-4 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white borderdark:text-white dark:hover:text-white dark:bg-gray-600 dark:hover:bg-gray-700 dark:border-gray-600 dark:hover:border-gray-600 border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none">
{{ white_automation_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
<line data-cap="butt" x1="5" y1="1" x2="5" y2="6" stroke="#ffffff"></line>
<line x1="3" y1="1" x2="7" y2="1" stroke="#fffffwww"></line>
<line data-cap="butt" x1="19" y1="1" x2="19" y2="6" stroke="#ffffff"></line>
<line x1="17" y1="1" x2="21" y2="1" stroke="#ffffff"></line>
<rect x="6" y="15" width="12" height="4" stroke="#ffffff"></rect>
<line data-cap="butt" x1="10" y1="19" x2="10" y2="15" stroke="#ffffff"></line>
<line data-cap="butt" x1="14" y1="19" x2="14" y2="15" stroke="#ffffff"></line>
<line x1="6" y1="11" x2="8" y2="11" stroke="#ffffff"></line>
<line x1="16" y1="11" x2="18" y2="11" stroke="#fff"></line>
<polygon points="23 6 5 6 1 6 1 23 23 23 23 6"></polygon>
</g>
</svg>
<span>Create New Strategy</span> <span>Create New Strategy</span>
</a> </a>
</div> </div>
@@ -100,11 +121,30 @@
<div class="px-6"> <div class="px-6">
<div class="flex flex-wrap justify-end"> <div class="flex flex-wrap justify-end">
<div class="w-full md:w-auto p-1.5 ml-2"> <div class="w-full md:w-auto p-1.5 ml-2">
<button name='clearfilters' value="Clear Filters" class="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">Clear Filters</button> <button name='clearfilters' value="Clear Filters" 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">
<svg class="mr-2 w-5 h-5" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
<line x1="20" y1="2" x2="12.329" y2="11.506"></line>
<path d="M11,11a2,2,0,0,1,2,2,3.659,3.659,0,0,1-.2.891A9.958,9.958,0,0,0,13.258,23H1C1,16.373,4.373,11,11,11Z"></path>
<line x1="18" y1="15" x2="23" y2="15" stroke="#ffffff"></line>
<line x1="17" y1="19" x2="23" y2="19" stroke="#ffffff"></line>
<line x1="19" y1="23" x2="23" y2="23" stroke="#ffffff"></line>
<path d="M8.059,11.415A3.9,3.9,0,0,0,12,16c.041,0,.079-.011.12-.012" data-cap="butt"></path>
<path d="M5,23a13.279,13.279,0,0,1,.208-3.4" data-cap="butt"></path>
<path d="M9.042,23c-.688-1.083-.313-3.4-.313-3.4" data-cap="butt"></path>
</g>
</svg> Clear</button>
</div> </div>
<div class="w-full md:w-auto p-1.5 ml-2"> <div class="w-full md:w-auto p-1.5 ml-2">
<button name="" value="Submit" type="submit" 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"> <button name="" value="Submit" 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">
{{ filter_apply_svg | safe }} Apply Filters</button> <svg class="mr-2 w-5 h-5" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
<rect x="2" y="2" width="7" height="7"></rect>
<rect x="15" y="15" width="7" height="7"></rect>
<rect x="2" y="15" width="7" height="7"></rect>
<polyline points="15 6 17 8 22 3" stroke="#ffffff"></polyline>
</g>
</svg>Apply Filters</button>
</div> </div>
</div> </div>
</div> </div>
@@ -164,8 +204,10 @@
<div class="flex flex-wrap justify-end"> <div class="flex flex-wrap justify-end">
<div class="w-full md:w-auto p-1.5"> <div class="w-full md:w-auto p-1.5">
<button type="submit" name='pageback' value="Page Back" class="inline-flex items-center h-9 py-1 px-4 text-xs text-blue-50 font-semibold bg-blue-500 hover:bg-blue-600 rounded-lg transition duration-200 focus:ring-0 focus:outline-none"> <button type="submit" name='pageback' value="Page Back" class="inline-flex items-center h-9 py-1 px-4 text-xs text-blue-50 font-semibold bg-blue-500 hover:bg-blue-600 rounded-lg transition duration-200 focus:ring-0 focus:outline-none">
{{ page_back_svg | safe }} <svg aria-hidden="true" class="mr-2 w-5 h-5" fill="#ffffff" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<span>Previous</span> <path fill-rule="evenodd" d="M7.707 14.707a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 1.414L5.414 9H17a1 1 0 110 2H5.414l2.293 2.293a1 1 0 010 1.414z" clip-rule="evenodd"></path>
</svg>
<span>Page Back</span>
</button> </button>
</div> </div>
<div class="flex items-center"> <div class="flex items-center">
@@ -175,8 +217,10 @@
</div> </div>
<div class="w-full md:w-auto p-1.5"> <div class="w-full md:w-auto p-1.5">
<button type="submit" name='pageforwards' value="Page Forwards" class="inline-flex items-center h-9 py-1 px-4 text-xs text-blue-50 font-semibold bg-blue-500 hover:bg-blue-600 rounded-lg transition duration-200 focus:ring-0 focus:outline-none"> <button type="submit" name='pageforwards' value="Page Forwards" class="inline-flex items-center h-9 py-1 px-4 text-xs text-blue-50 font-semibold bg-blue-500 hover:bg-blue-600 rounded-lg transition duration-200 focus:ring-0 focus:outline-none">
<span>Next</span> <span>Page Forwards</span>
{{ page_forwards_svg | safe }} <svg aria-hidden="true" class="ml-2 w-5 h-5" fill="#ffffff" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M12.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-2.293-2.293a1 1 0 010-1.414z" clip-rule="evenodd"></path>
</svg>
</button> </button>
</div> </div>
</div> </div>

View File

@@ -1,5 +1,4 @@
{% include 'header.html' %} {% include 'header.html' %}
{% from 'style.html' import breadcrumb_line_svg %}
<div class="container mx-auto"> <div class="container mx-auto">
<section class="p-5 mt-5"> <section class="p-5 mt-5">
<div class="flex flex-wrap items-center -m-2"> <div class="flex flex-wrap items-center -m-2">
@@ -9,13 +8,21 @@
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/"> <a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/">
<p>Home</p> <p>Home</p>
</a> </a>
<li>{{ breadcrumb_line_svg | safe }}</li> <li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
<li> <li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/automation">Automation Strategies</a> <a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/automation">Automation Strategies</a>
</li> </li>
<li>{{ breadcrumb_line_svg | safe }}</li>
<li> <li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/automation">ID:<!-- todo ID here {{ strategy_id }} --></a> <svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
<li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/automation">ID: <!-- todo ID here {{ strategy_id }} --></a>
</li> </li>
</ul> </ul>
</ul> </ul>
@@ -31,7 +38,7 @@
<div class="relative z-20 flex flex-wrap items-center -m-3"> <div class="relative z-20 flex flex-wrap items-center -m-3">
<div class="w-full md:w-1/2 p-3"> <div class="w-full md:w-1/2 p-3">
<h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">Automation Strategy {{ strategy_id }}</h2> <h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">Automation Strategy {{ strategy_id }}</h2>
<p class="font-normal text-coolGray-200 dark:text-white"><span class="bold">ID:</span><!-- todo ID here {{ strategy_id }} --> <p class="font-normal text-coolGray-200 dark:text-white">ID: <!-- todo ID here {{ strategy_id }} -->
</p> </p>
</div> </div>
</div> </div>
@@ -59,7 +66,7 @@
</th> </th>
<th class="p-0"> <th class="p-0">
<div class="py-3 px-6 bg-coolGray-200 dark:bg-gray-600"> <div class="py-3 px-6 bg-coolGray-200 dark:bg-gray-600">
<span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">Input</span> <span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">Type</span>
</div> </div>
</th> </th>
</tr> </tr>
@@ -107,17 +114,42 @@
<div class="flex flex-wrap justify-end"> <div class="flex flex-wrap justify-end">
{% if show_edit_form %} {% if show_edit_form %}
<div class="w-full md:w-auto p-1.5 ml-2"> <div class="w-full md:w-auto p-1.5 ml-2">
<button name="apply" value="Apply" 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">Apply</button> <button name="apply" value="Apply" 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">
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
<polyline points=" 6,12 10,16 18,8 " stroke="#ffffff"></polyline>
<circle cx="12" cy="12" r="11"></circle>
</g>
</svg>Apply</button>
</div> </div>
<div class="w-full md:w-auto p-1.5 ml-2"> <div class="w-full md:w-auto p-1.5 ml-2">
<button name="cancel" value="Cancel" type="submit" class="flex flex-wrap justify-center w-full px-4 py-2.5 bg-red-500 hover:bg-red-600 font-medium text-sm text-white border border-red-500 rounded-md shadow-button focus:ring-0 focus:outline-none">Cancel</button> <button name="cancel" value="Cancel" type="submit" class="flex flex-wrap justify-center w-full px-4 py-2.5 bg-red-500 hover:bg-red-600 font-medium text-sm text-white border border-red-500 rounded-md shadow-button focus:ring-0 focus:outline-none" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
</div> <g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ef5844" stroke-linejoin="round">
{% else %} <line x1="16" y1="8" x2="8" y2="16" stroke="#ef5844"></line>
<div class="w-full md:w-auto p-1.5"> <line x1="16" y1="16" x2="8" y2="8" stroke="#ef5844"></line>
<button name="edit" value="edit" 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">Edit</button> <circle cx="12" cy="12" r="11"></circle>
</g>
</svg>Cancel</button>
</div> {% else %} <div class="w-full md:w-auto p-1.5">
<button name="edit" value="edit" 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">
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
<line x1="2" y1="23" x2="22" y2="23" stroke="#ffffff"></line>
<line data-cap="butt" x1="13" y1="5" x2="17" y2="9"></line>
<polygon points="8 18 3 19 4 14 16 2 20 6 8 18"></polygon>
</g>
</svg>Edit</button>
</div> </div>
<div class="w-full md:w-auto p-1.5 ml-2"> <div class="w-full md:w-auto p-1.5 ml-2">
<a href="/automation" 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"><span>Back</span> <a href="/automation" 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">
<svg class="text-gray-500 w-5 h-5 mr-2" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="square" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="miter" class="nc-icon-wrapper" stroke-miterlimit="10">
<line data-cap="butt" x1="18" y1="12" x2="7" y2="12" stroke-linecap="butt" stroke="#ffffff"></line>
<polyline points=" 11,16 7,12 11,8 " stroke="#ffffff"></polyline>
<circle cx="12" cy="12" r="11"></circle>
</g>
</svg>
<span>Back</span>
</a> </a>
</div> </div>
{% endif %} {% endif %}

View File

@@ -1,5 +1,4 @@
{% include 'header.html' %} {% include 'header.html' %}
{% from 'style.html' import breadcrumb_line_svg %}
<div class="container mx-auto"> <div class="container mx-auto">
<section class="p-5 mt-5"> <section class="p-5 mt-5">
<div class="flex flex-wrap items-center -m-2"> <div class="flex flex-wrap items-center -m-2">
@@ -9,13 +8,21 @@
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/"> <a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/">
<p>Home</p> <p>Home</p>
</a> </a>
<li>{{ breadcrumb_line_svg | safe }}</li> <li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
<li> <li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/automation">Automation Strategies</a> <a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/automation">Automation Strategies</a>
</li> </li>
<li>{{ breadcrumb_line_svg | safe }}</li>
<li> <li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/automation">New</a> <svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
<li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/newautomationstrategy">New</a>
</li> </li>
</ul> </ul>
</ul> </ul>
@@ -31,14 +38,14 @@
<div class="relative z-20 flex flex-wrap items-center -m-3"> <div class="relative z-20 flex flex-wrap items-center -m-3">
<div class="w-full md:w-1/2 p-3"> <div class="w-full md:w-1/2 p-3">
<h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">New Automation Strategy</h2> <h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">New Automation Strategy</h2>
<p class="font-normal text-coolGray-200 dark:text-white"><span class="bold">TODO/WIP:</span> <p class="font-normal text-coolGray-200 dark:text-white">Todo <!-- todo -->
</p> </p>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
{% include 'inc_messages.html' %} {% include 'inc_messages.html' %}
<section> <section>
<div class="pl-6 pr-6 pt-0 pb-0 mt-5 h-full overflow-hidden"> <div class="pl-6 pr-6 pt-0 pb-0 mt-5 h-full overflow-hidden">
<div class="pb-6 border-coolGray-100"> <div class="pb-6 border-coolGray-100">

View File

@@ -1,6 +1,4 @@
{% include 'header.html' %} {% include 'header.html' %}
{% from 'style.html' import breadcrumb_line_svg, circular_arrows_svg, input_arrow_down_svg, small_arrow_white_right_svg %}
<div class="container mx-auto"> <div class="container mx-auto">
<section class="p-5 mt-5"> <section class="p-5 mt-5">
<div class="flex flex-wrap items-center -m-2"> <div class="flex flex-wrap items-center -m-2">
@@ -11,11 +9,19 @@
<p>Home</p> <p>Home</p>
</a> </a>
</li> </li>
<li> {{ breadcrumb_line_svg | safe }} </li> <li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
<li> <li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="#">Bids</a> <a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="#">Bids</a>
</li> </li>
<li> {{ breadcrumb_line_svg | safe }} </li> <li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
<li> <li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="{{ bid_id }}">BID ID: {{ bid_id }}</a> <a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="{{ bid_id }}">BID ID: {{ bid_id }}</a>
</li> </li>
@@ -32,17 +38,23 @@
<div class="relative z-20 flex flex-wrap items-center -m-3"> <div class="relative z-20 flex flex-wrap items-center -m-3">
<div class="w-full md:w-1/2 p-3"> <div class="w-full md:w-1/2 p-3">
<h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">Bid {% if debug_mode == true %} (Debug: bid template) {% endif %}</h2> <h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">Bid {% if debug_mode == true %} (Debug: bid template) {% endif %}</h2>
<p class="font-normal text-coolGray-200 dark:text-white"><span class="bold">BID ID:</span> {{ bid_id }}</p> <p class="font-normal text-coolGray-200 dark:text-white">Bid ID: {{ bid_id }}</p>
</div> </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"> <div class="w-full md:w-1/2 p-3 p-6 container flex flex-wrap items-center justify-end items-center mx-auto"> {% if refresh %} <a id="refresh" href="/bid/{{ bid_id }}" class="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">
{% if refresh %} <svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<a id="refresh" href="/bid/{{ bid_id }}" class="rounded-full 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"> <g fill="#ffffff">
{{ circular_arrows_svg | safe }} <path fill="#ffffff" d="M12,3c1.989,0,3.873,0.65,5.43,1.833l-3.604,3.393l9.167,0.983L22.562,0l-3.655,3.442 C16.957,1.862,14.545,1,12,1C5.935,1,1,5.935,1,12h2C3,7.037,7.037,3,12,3z"></path>
<path data-color="color-2" d="M12,21c-1.989,0-3.873-0.65-5.43-1.833l3.604-3.393l-9.167-0.983L1.438,24l3.655-3.442 C7.043,22.138,9.455,23,12,23c6.065,0,11-4.935,11-11h-2C21,16.963,16.963,21,12,21z"></path>
</g>
</svg>
<span>Refresh {{ refresh }} seconds</span> <span>Refresh {{ refresh }} seconds</span>
</a> </a> {% else %} <a id="refresh" href="/bid/{{ bid_id }}" class="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">
{% else %} <svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<a id="refresh" href="/bid/{{ bid_id }}" class="rounded-full 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"> <g fill="#ffffff">
{{ circular_arrows_svg | safe }} <path fill="#ffffff" d="M12,3c1.989,0,3.873,0.65,5.43,1.833l-3.604,3.393l9.167,0.983L22.562,0l-3.655,3.442 C16.957,1.862,14.545,1,12,1C5.935,1,1,5.935,1,12h2C3,7.037,7.037,3,12,3z"></path>
<path data-color="color-2" d="M12,21c-1.989,0-3.873-0.65-5.43-1.833l3.604-3.393l-9.167-0.983L1.438,24l3.655-3.442 C7.043,22.138,9.455,23,12,23c6.065,0,11-4.935,11-11h-2C21,16.963,16.963,21,12,21z"></path>
</g>
</svg>
<span>Refresh</span> <span>Refresh</span>
</a> </a>
{% endif %} {% endif %}
@@ -82,7 +94,9 @@
<td class="py-3 px-6"> <td class="py-3 px-6">
<div class="content flex py-2"> <div class="content flex py-2">
<span class="bold">{{ data.amt_to }} {{ data.ticker_to }}</span> <span class="bold">{{ data.amt_to }} {{ data.ticker_to }}</span>
{{ small_arrow_white_right_svg | safe }} <svg aria-hidden="true " class="w-5 h-5 ml-3 mr-3" fill="currentColor " viewBox="0 0 20 20 " xmlns="http://www.w3.org/2000/svg ">
<path fill-rule="evenodd " d="M12.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-2.293-2.293a1 1 0 010-1.414z " clip-rule="evenodd "></path>
</svg>
<span class="text-xs bold">{{ data.amt_from }} {{ data.ticker_from }}</span> <span class="text-xs bold">{{ data.amt_from }} {{ data.ticker_from }}</span>
</div> </div>
</td> </td>
@@ -93,7 +107,9 @@
<td class="py-3 px-6"> <td class="py-3 px-6">
<div class="content flex py-2"> <div class="content flex py-2">
<span class="bold">{{ data.amt_from }} {{ data.ticker_from }}</span> <span class="bold">{{ data.amt_from }} {{ data.ticker_from }}</span>
{{ small_arrow_white_right_svg | safe }} <svg aria-hidden="true " class="w-5 h-5 ml-3 mr-3" fill="currentColor " viewBox="0 0 20 20 " xmlns="http://www.w3.org/2000/svg ">
<path fill-rule="evenodd " d="M12.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-2.293-2.293a1 1 0 010-1.414z " clip-rule="evenodd "></path>
</svg>
<span class="bold">{{ data.amt_to }} {{ data.ticker_to }}</span> <span class="bold">{{ data.amt_to }} {{ data.ticker_to }}</span>
</div> </div>
</td> </td>
@@ -445,7 +461,9 @@
<td class="py-3 px-6 bold">Change Bid State:</td> <td class="py-3 px-6 bold">Change Bid State:</td>
<td class="py-3 px-6"> <td class="py-3 px-6">
<div class="relative"> <div class="relative">
{{ input_arrow_down_svg| safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<select class="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-" name="new_state"> <select class="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-" name="new_state">
{% for s in data.bid_states %} {% for s in data.bid_states %}
<option value="{{ s[0] }}" {% if data.bid_state_ind==s[0] %} selected{% endif %}>{{ s[1] }}</option> <option value="{{ s[0] }}" {% if data.bid_state_ind==s[0] %} selected{% endif %}>{{ s[1] }}</option>
@@ -459,7 +477,9 @@
<td class="py-3 px-6 bold">Debug Option</td> <td class="py-3 px-6 bold">Debug Option</td>
<td class="py-3 px-6"> <td class="py-3 px-6">
<div class="relative"> <div class="relative">
{{ input_arrow_down_svg| safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<select class="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-" name="debugind"> <select class="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-" name="debugind">
<option{% if data.debug_ind=="-1" %} selected{% endif %} value="-1">None</option> <option{% if data.debug_ind=="-1" %} selected{% endif %} value="-1">None</option>
{% for a in data.debug_options %} {% for a in data.debug_options %}
@@ -541,7 +561,7 @@
<button name="abandon_bid" type="submit" value="Abandon Bid" onclick="return confirmPopup();" 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">Abandon Bid</button> <button name="abandon_bid" type="submit" value="Abandon Bid" onclick="return confirmPopup();" 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">Abandon Bid</button>
</div> </div>
{% endif %} {% endif %}
{% if data.was_received == 'True' and not edit_bid and data.can_accept_bid %} {% if data.was_received == 'True' and not edit_bid %}
<div class="w-full md:w-auto p-1.5"> <div class="w-full md:w-auto p-1.5">
<button name="accept_bid" value="Accept Bid" type="submit" onclick='return confirmPopup("Accept");' 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">Accept Bid</button> <button name="accept_bid" value="Accept Bid" type="submit" onclick='return confirmPopup("Accept");' 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">Accept Bid</button>
</div> </div>

View File

@@ -1,5 +1,5 @@
{% include 'header.html' %} {% include 'header.html' %}
{% from 'style.html' import breadcrumb_line_svg, circular_arrows_svg, input_arrow_down_svg, small_arrow_white_right_svg %} {% from 'style.html' import input_arrow_down_svg %}
<div class="container mx-auto"> <div class="container mx-auto">
<section class="p-5 mt-5"> <section class="p-5 mt-5">
@@ -11,11 +11,19 @@
<p>Home</p> <p>Home</p>
</a> </a>
</li> </li>
<li> {{ breadcrumb_line_svg | safe }} </li> <li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
<li> <li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="#">Bids</a> <a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="#">Bids</a>
</li> </li>
<li> {{ breadcrumb_line_svg | safe }} </li> <li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
<li> <li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="{{ bid_id }}">BID ID: {{ bid_id }}</a> <a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="{{ bid_id }}">BID ID: {{ bid_id }}</a>
</li> </li>
@@ -32,17 +40,25 @@
<div class="relative z-20 flex flex-wrap items-center -m-3"> <div class="relative z-20 flex flex-wrap items-center -m-3">
<div class="w-full md:w-1/2 p-3"> <div class="w-full md:w-1/2 p-3">
<h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">Bid {% if debug_mode == true %} (Debug: bid_xmr template) {% endif %}</h2> <h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">Bid {% if debug_mode == true %} (Debug: bid_xmr template) {% endif %}</h2>
<p class="font-normal text-coolGray-200 dark:text-white"><span class="bold">BID ID:</span> {{ bid_id }}</p> <p class="font-normal text-coolGray-200 dark:text-white">Bid ID: {{ bid_id }}</p>
</div> </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"> <div class="w-full md:w-1/2 p-3 p-6 container flex flex-wrap items-center justify-end items-center mx-auto"> {% if refresh %} <a id="refresh" href="/bid/{{ bid_id }}" class="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">
{% if refresh %} <svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<a id="refresh" href="/bid/{{ bid_id }}" class="rounded-full 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"> <g fill="#ffffff">
{{ circular_arrows_svg | safe }} <path fill="#ffffff" d="M12,3c1.989,0,3.873,0.65,5.43,1.833l-3.604,3.393l9.167,0.983L22.562,0l-3.655,3.442 C16.957,1.862,14.545,1,12,1C5.935,1,1,5.935,1,12h2C3,7.037,7.037,3,12,3z"></path>
<path data-color="color-2" d="M12,21c-1.989,0-3.873-0.65-5.43-1.833l3.604-3.393l-9.167-0.983L1.438,24l3.655-3.442 C7.043,22.138,9.455,23,12,23c6.065,0,11-4.935,11-11h-2C21,16.963,16.963,21,12,21z"></path>
</g>
</svg>
<span>Refresh {{ refresh }} seconds</span> <span>Refresh {{ refresh }} seconds</span>
</a> </a>
{% else %} {% else %}
<a id="refresh" href="/bid/{{ bid_id }}" class="rounded-full 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"> <a id="refresh" href="/bid/{{ bid_id }}" class="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">
{{ circular_arrows_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g fill="#ffffff">
<path fill="#ffffff" d="M12,3c1.989,0,3.873,0.65,5.43,1.833l-3.604,3.393l9.167,0.983L22.562,0l-3.655,3.442 C16.957,1.862,14.545,1,12,1C5.935,1,1,5.935,1,12h2C3,7.037,7.037,3,12,3z"></path>
<path data-color="color-2" d="M12,21c-1.989,0-3.873-0.65-5.43-1.833l3.604-3.393l-9.167-0.983L1.438,24l3.655-3.442 C7.043,22.138,9.455,23,12,23c6.065,0,11-4.935,11-11h-2C21,16.963,16.963,21,12,21z"></path>
</g>
</svg>
<span>Refresh</span> <span>Refresh</span>
</a> </a>
{% endif %} {% endif %}
@@ -82,8 +98,10 @@
<td class="py-3 px-6"> <td class="py-3 px-6">
<div class="content flex py-2"> <div class="content flex py-2">
<span class="bold">{{ data.amt_to }} {{ data.ticker_to }}</span> <span class="bold">{{ data.amt_to }} {{ data.ticker_to }}</span>
{{ small_arrow_white_right_svg | safe }} <svg aria-hidden="true " class="w-5 h-5 ml-3 mr-3" fill="currentColor " viewBox="0 0 20 20 " xmlns="http://www.w3.org/2000/svg ">
<span class="bold">{{ data.amt_from }} {{ data.ticker_from }}</span> <path fill-rule="evenodd " d="M12.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-2.293-2.293a1 1 0 010-1.414z " clip-rule="evenodd "></path>
</svg>
<span class="text-xs bold">{{ data.amt_from }} {{ data.ticker_from }}</span>
</div> </div>
</td> </td>
</tr> </tr>
@@ -93,7 +111,9 @@
<td class="py-3 px-6"> <td class="py-3 px-6">
<div class="content flex py-2"> <div class="content flex py-2">
<span class="bold">{{ data.amt_from }} {{ data.ticker_from }}</span> <span class="bold">{{ data.amt_from }} {{ data.ticker_from }}</span>
{{ small_arrow_white_right_svg | safe }} <svg aria-hidden="true " class="w-5 h-5 ml-3 mr-3" fill="currentColor " viewBox="0 0 20 20 " xmlns="http://www.w3.org/2000/svg ">
<path fill-rule="evenodd " d="M12.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-2.293-2.293a1 1 0 010-1.414z " clip-rule="evenodd "></path>
</svg>
<span class="bold">{{ data.amt_to }} {{ data.ticker_to }}</span> <span class="bold">{{ data.amt_to }} {{ data.ticker_to }}</span>
</div> </div>
</td> </td>
@@ -485,8 +505,7 @@
<tr class="opacity-100 text-gray-500 dark:text-gray-100"> <tr class="opacity-100 text-gray-500 dark:text-gray-100">
<td class="py-3 px-6 bold">View Transaction:</td> <td class="py-3 px-6 bold">View Transaction:</td>
<td class="py-3 px-6 bold"> <td class="py-3 px-6 bold">
<div class="relative"> <div class="relative">{{ input_arrow_down_svg | safe }}
{{ input_arrow_down_svg | safe }}
<select class="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" name="view_tx"> <select class="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" name="view_tx">
{% if data.txns|length %} {% for tx in data.txns %} {% if data.txns|length %} {% for tx in data.txns %}
<option value="{{ tx.txid }}" {% if data.view_tx_ind==tx.txid %} selected{% endif %}>{{ tx.type }} {{ tx.txid }}</option> <option value="{{ tx.txid }}" {% if data.view_tx_ind==tx.txid %} selected{% endif %}>{{ tx.type }} {{ tx.txid }}</option>
@@ -703,8 +722,7 @@
<tr class="opacity-100 text-gray-500 dark:text-gray-100"> <tr class="opacity-100 text-gray-500 dark:text-gray-100">
<td class="py-3 px-6 bold">Change Bid State:</td> <td class="py-3 px-6 bold">Change Bid State:</td>
<td class="py-3 px-6"> <td class="py-3 px-6">
<div class="relative"> <div class="relative">{{ input_arrow_down_svg | safe }}
{{ input_arrow_down_svg | safe }}
<select class="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" name="new_state"> <select class="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" name="new_state">
{% for s in data.bid_states %} {% for s in data.bid_states %}
<option value="{{ s[0] }}" {% if data.bid_state_ind==s[0] %} selected{% endif %}>{{ s[1] }}</option> <option value="{{ s[0] }}" {% if data.bid_state_ind==s[0] %} selected{% endif %}>{{ s[1] }}</option>
@@ -717,8 +735,7 @@
<tr class="opacity-100 text-gray-500 dark:text-gray-100"> <tr class="opacity-100 text-gray-500 dark:text-gray-100">
<td class="py-3 px-6 bold">Add Bid Action:</td> <td class="py-3 px-6 bold">Add Bid Action:</td>
<td class="py-3 px-6"> <td class="py-3 px-6">
<div class="relative"> <div class="relative">{{ input_arrow_down_svg | safe }}
{{ input_arrow_down_svg | safe }}
<select class="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" name="new_action"> <select class="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" name="new_action">
{% for a in data.bid_actions %} {% for a in data.bid_actions %}
<option value="{{ a[0] }}">{{ a[1] }}</option> <option value="{{ a[0] }}">{{ a[1] }}</option>
@@ -730,8 +747,7 @@
<tr class="opacity-100 text-gray-500 dark:text-gray-100"> <tr class="opacity-100 text-gray-500 dark:text-gray-100">
<td class="py-3 px-6 bold">Debug Option</td> <td class="py-3 px-6 bold">Debug Option</td>
<td class="py-3 px-6"> <td class="py-3 px-6">
<div class="relative"> <div class="relative">{{ input_arrow_down_svg | safe }}
{{ input_arrow_down_svg | safe }}
<select class="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" name="debugind"> <select class="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" name="debugind">
<option{% if data.debug_ind=="-1" %} selected{% endif %} value="-1">None</option> <option{% if data.debug_ind=="-1" %} selected{% endif %} value="-1">None</option>
{% for a in data.debug_options %} {% for a in data.debug_options %}
@@ -817,7 +833,7 @@
<button name="abandon_bid" type="submit" value="Abandon Bid" onclick="return confirmPopup();" 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 focus:ring-0 focus:outline-none">Abandon Bid</button> <button name="abandon_bid" type="submit" value="Abandon Bid" onclick="return confirmPopup();" 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 focus:ring-0 focus:outline-none">Abandon Bid</button>
</div> </div>
{% endif %} {% endif %}
{% if data.was_received == 'True' and not edit_bid and data.can_accept_bid %} {% if data.was_received == 'True' and not edit_bid %}
<div class="w-full md:w-auto p-1.5"> <div class="w-full md:w-auto p-1.5">
<button name="accept_bid" value="Accept Bid" type="submit" onclick='return confirmPopup("Accept");' 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 focus:ring-0 focus:outline-none">Accept Bid</button> <button name="accept_bid" value="Accept Bid" type="submit" onclick='return confirmPopup("Accept");' 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 focus:ring-0 focus:outline-none">Accept Bid</button>
</div> </div>

View File

@@ -1,16 +1,27 @@
{% include 'header.html' %} {% include 'header.html' %}
{% from 'style.html' import breadcrumb_line_svg, page_back_svg, page_forwards_svg, filter_clear_svg, filter_apply_svg, circular_arrows_svg, input_arrow_down_svg %}
<div class="container mx-auto"> <div class="container mx-auto">
<section class="p-5 mt-5"> <section class="p-5 mt-5">
<div class="flex flex-wrap items-center -m-2"> <div class="flex flex-wrap items-center -m-2">
<div class="w-full md:w-1/2 p-2"> <div class="w-full md:w-1/2 p-2">
<ul class="flex flex-wrap items-center gap-x-3 mb-2"> <ul class="flex flex-wrap items-center gap-x-3 mb-2">
<li> <li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/"><p>Home</p></a> <a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/">
<p>Home</p>
</a>
</li>
<li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
<li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="#">{{ page_type_available }} {{ page_type_received }} {{ page_type_sent }}</a>
</li>
<li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li> </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="#">{{ page_type_available }} {{ page_type_received }} {{ page_type_sent }}</a> </li>
<li> {{ breadcrumb_line_svg | safe }} </li>
</ul> </ul>
</div> </div>
</div> </div>
@@ -18,17 +29,21 @@
<section class="py-4"> <section class="py-4">
<div class="container px-4 mx-auto"> <div class="container px-4 mx-auto">
<div class="relative py-11 px-16 bg-coolGray-900 dark:bg-blue-500 rounded-md overflow-hidden"> <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" src="/static/images/elements/dots-red.svg" alt=""> <img class="absolute z-10 right-4 bottom-4" src="/static/images/elements/dots-red.svg" alt=""> <img class="absolute z-10 left-4 top-4" src="/static/images/elements/dots-red.svg" alt="">
<img class="absolute z-10 right-4 bottom-4" src="/static/images/elements/dots-red.svg" alt="">
<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=""> <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="">
<div class="relative z-20 flex flex-wrap items-center -m-3"> <div class="relative z-20 flex flex-wrap items-center -m-3">
<div class="w-full md:w-1/2 p-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_available }} {{ page_type_received }} {{ page_type_sent }}</h2> <h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">{{ page_type_available }} {{ page_type_received }} {{ page_type_sent }}</h2>
<p class="font-normal text-coolGray-200 dark:text-white">{{ page_type_available_description }} {{ page_type_received_description }} {{ page_type_sent_description }}</p> <p class="font-normal text-coolGray-200 dark:text-white">{{ page_type_available_description }} {{ page_type_received_description }} {{ page_type_sent_description }}</p>
</div> </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"> <div class="w-full md:w-1/2 p-3 p-6 container flex flex-wrap items-center justify-end items-center mx-auto"> {% if refresh %} <a id="refresh" href="/bid/{{ bid_id }}" class="flex flex-wrap justify-center px-5 py-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">
{% if refresh %} <svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<a id="refresh" href="/bid/{{ bid_id }}" 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"> <g fill="#ffffff">
{{ circular_arrows_svg | safe }} <path fill="#ffffff" d="M12,3c1.989,0,3.873,0.65,5.43,1.833l-3.604,3.393l9.167,0.983L22.562,0l-3.655,3.442 C16.957,1.862,14.545,1,12,1C5.935,1,1,5.935,1,12h2C3,7.037,7.037,3,12,3z"></path>
<path data-color="color-2" d="M12,21c-1.989,0-3.873-0.65-5.43-1.833l3.604-3.393l-9.167-0.983L1.438,24l3.655-3.442 C7.043,22.138,9.455,23,12,23c6.065,0,11-4.935,11-11h-2C21,16.963,16.963,21,12,21z"></path>
</g>
</svg>
<span>Refresh {{ refresh }} seconds</span> <span>Refresh {{ refresh }} seconds</span>
</a> </a>
{% endif %} {% endif %}
@@ -41,15 +56,17 @@
<div class="pl-6 pr-6 pt-0 pb-0 mt-5 h-full overflow-hidden"> <div class="pl-6 pr-6 pt-0 pb-0 mt-5 h-full overflow-hidden">
<div class="pb-6 border-coolGray-100"> <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 -m-2">
<div class="w-full mx-auto pt-2"> <div class="w-full pt-2">
<form method="post"> <form method="post">
<div class="flex items-center justify-center pb-4 dark:text-white"> <div class="flex justify-between items-center pb-4 dark:text-white">
<div class="rounded-b-md"> <div class="rounded-b-md">
<div class="w-full md:w-0/12"> <div class="w-full md:w-0/12">
<div class="flex flex-wrap justify-center -m-1.5"> <div class="flex flex-wrap justify-end -m-1.5">
<div class="w-full md:w-auto p-1.5"> <div class="w-full md:w-auto p-1.5">
<div class="relative"> <div class="relative">
{{ input_arrow_down_svg | safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<select name="sort_by" 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"> <select name="sort_by" 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">
<option value="created_at" {% if filters.sort_by=='created_at' %} selected{% endif %}>Time At</option> <option value="created_at" {% if filters.sort_by=='created_at' %} selected{% endif %}>Time At</option>
</select> </select>
@@ -57,7 +74,9 @@
</div> </div>
<div class="w-full md:w-auto p-1.5"> <div class="w-full md:w-auto p-1.5">
<div class="relative"> <div class="relative">
{{ input_arrow_down_svg | safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<select name="sort_dir" 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"> <select name="sort_dir" 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">
<option value="asc" {% if filters.sort_dir=='asc' %} selected{% endif %}>Ascending</option> <option value="asc" {% if filters.sort_dir=='asc' %} selected{% endif %}>Ascending</option>
<option value="desc" {% if filters.sort_dir=='desc' %} selected{% endif %}>Descending</option> <option value="desc" {% if filters.sort_dir=='desc' %} selected{% endif %}>Descending</option>
@@ -71,7 +90,9 @@
</div> </div>
<div class="w-full md:w-auto p-1.5"> <div class="w-full md:w-auto p-1.5">
<div class="relative"> <div class="relative">
{{ input_arrow_down_svg | safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<select name="state" 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"> <select name="state" 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">
<option value="-1" {% if filters.bid_state_ind==-1 %} selected{% endif %}>Any</option> <option value="-1" {% if filters.bid_state_ind==-1 %} selected{% endif %}>Any</option>
{% for s in data.bid_states %} {% for s in data.bid_states %}
@@ -87,22 +108,45 @@
</div> </div>
<div class="w-full md:w-auto p-1.5"> <div class="w-full md:w-auto p-1.5">
<div class="relative"> <div class="relative">
{{ input_arrow_down_svg | safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<select name="with_expired" 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"> <select name="with_expired" 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">
<option value="true" {% if filters.with_expired==true %} selected{% endif %}>Include</option> <option value="true" {% if filters.with_expired==true %} selected{% endif %}>Include</option>
<option value="false" {% if filters.with_expired==false %} selected{% endif %}>Exclude</option> <option value="false" {% if filters.with_expired==false %} selected{% endif %}>Exclude</option>
</select> </div> </select>
</div>
</div> </div>
<div class="w-full md:w-auto p-1.5"> <div class="w-full md:w-auto p-1.5">
<div class="relative"> <div class="relative">
<button type="submit" name='clearfilters' value="Clear Filters" class="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"> <button type="submit" name='clearfilters' value="Clear Filters" class="flex flex-wrap justify-center w-full px-4 py-2.5 font-medium text-sm text-white bg-blue-500 hover:bg-blue-600 rounded-lg transition duration-200 border border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none">
<span>Clear Filters</span> <svg class="mr-2 w-5 h-5" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#fff" stroke-linejoin="round">
<line x1="20" y1="2" x2="12.329" y2="11.506"></line>
<path d="M11,11a2,2,0,0,1,2,2,3.659,3.659,0,0,1-.2.891A9.958,9.958,0,0,0,13.258,23H1C1,16.373,4.373,11,11,11Z"></path>
<line x1="18" y1="15" x2="23" y2="15" stroke="#fff"></line>
<line x1="17" y1="19" x2="23" y2="19" stroke="#fff"></line>
<line x1="19" y1="23" x2="23" y2="23" stroke="#fff"></line>
<path d="M8.059,11.415A3.9,3.9,0,0,0,12,16c.041,0,.079-.011.12-.012" data-cap="butt"></path>
<path d="M5,23a13.279,13.279,0,0,1,.208-3.4" data-cap="butt"></path>
<path d="M9.042,23c-.688-1.083-.313-3.4-.313-3.4" data-cap="butt"></path>
</g>
</svg>
<span>Clear</span>
</button> </button>
</div> </div>
</div> </div>
<div class="w-full md:w-auto p-1.5"> <div class="w-full md:w-auto p-1.5">
<div class="relative"> <button type="submit" name='applyfilters' value="Apply Filters" 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"> <div class="relative">
{{ filter_apply_svg | safe }} <button type="submit" name='applyfilters' value="Apply Filters" class="flex flex-wrap justify-center w-full px-4 py-2.5 font-medium text-sm text-white bg-blue-500 hover:bg-blue-600 rounded-lg transition duration-200 border border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none">
<svg class="mr-2 w-5 h-5" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#fff" stroke-linejoin="round">
<rect x="2" y="2" width="7" height="7"></rect>
<rect x="15" y="15" width="7" height="7"></rect>
<rect x="2" y="15" width="7" height="7"></rect>
<polyline points="15 6 17 8 22 3" stroke="#fff"></polyline>
</g>
</svg>
<span>Apply Filters</span> <span>Apply Filters</span>
</button> </button>
</div> </div>
@@ -119,35 +163,43 @@
<thead class="uppercase"> <thead class="uppercase">
<tr class="text-left"> <tr class="text-left">
<th class="p-0"> <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">Date/Time at</span> <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">Date/Time at</span>
</div> </div>
</th> </th>
<th class="p-0"> <th class="p-0">
<div class="py-3 px-6 bg-coolGray-200 dark:bg-gray-600"> <span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">Bid ID</span> <div class="py-3 px-6 bg-coolGray-200 dark:bg-gray-600">
<span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">Bid ID</span>
</div> </div>
</th> </th>
<th class="p-0"> <th class="p-0">
<div class="py-3 px-6 bg-coolGray-200 dark:bg-gray-600"> <span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">Offer ID</span> <div class="py-3 px-6 bg-coolGray-200 dark:bg-gray-600">
<span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">Offer ID</span>
</div> </div>
</th> </th>
<th class="p-0"> <th class="p-0">
<div class="py-3 px-6 bg-coolGray-200 dark:bg-gray-600"> <span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">Bid From</span> <div class="py-3 px-6 bg-coolGray-200 dark:bg-gray-600">
<span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">Bid From</span>
</div> </div>
</th> </th>
<th class="p-0"> <th class="p-0">
<div class="py-3 px-6 bg-coolGray-200 dark:bg-gray-600"> <span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">Bid Status</span> <div class="py-3 px-6 bg-coolGray-200 dark:bg-gray-600">
<span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">Bid Status</span>
</div> </div>
</th> </th>
<th class="p-0"> <th class="p-0">
<div class="py-3 px-6 bg-coolGray-200 dark:bg-gray-600"> <span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">ITX Status</span> <div class="py-3 px-6 bg-coolGray-200 dark:bg-gray-600">
<span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">ITX Status</span>
</div> </div>
</th> </th>
<th class="p-0"> <th class="p-0">
<div class="py-3 px-6 bg-coolGray-200 dark:bg-gray-600"> <span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">PTX Status</span> <div class="py-3 px-6 bg-coolGray-200 dark:bg-gray-600">
<span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">PTX Status</span>
</div> </div>
</th> </th>
<th class="p-0"> <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 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>
</th> </th>
</tr> </tr>
@@ -155,7 +207,8 @@
<tbody> <tbody>
{% for b in bids %} {% for b in bids %}
<tr class="opacity-100 text-gray-500 dark:text-gray-100 hover:bg-coolGray-200 dark:hover:bg-gray-600"> <tr class="opacity-100 text-gray-500 dark:text-gray-100 hover:bg-coolGray-200 dark:hover:bg-gray-600">
<th scope="row" class="flex items-center py-7 px-46 text-gray-900 whitespace-nowrap"> <svg class="w-5 h-5 rounded-full ml-5" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24"> <th scope="row" class="flex items-center py-7 px-46 text-gray-900 whitespace-nowrap">
<svg class="w-5 h-5 rounded-full ml-5" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round"> <g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<circle cx="12" cy="12" r="11"></circle> <circle cx="12" cy="12" r="11"></circle>
<polyline points=" 12,6 12,12 18,12 " stroke="#6b7280"></polyline> <polyline points=" 12,6 12,12 18,12 " stroke="#6b7280"></polyline>
@@ -165,46 +218,59 @@
<div class="font-semibold text-xs dark:text-white">{{ b[0] }}</div> <div class="font-semibold text-xs dark:text-white">{{ b[0] }}</div>
</div> </div>
</th> </th>
<td class="py-3 px-6 text-xs monospace"> <a href=/bid/{{ b[1] }}>{{ b[1]|truncate(20, True) }}</a> </td> <td class="py-3 px-6 text-xs monospace">
<td class="py-3 px-6 text-xs monospace"> <a href=/offer/{{ b[2] }}>{{ b[2]|truncate(20, True) }}</a> </td> <a href=/bid/{{ b[1] }}>{{ b[1]|truncate(20, True) }}</a>
<td class="py-3 px-6 text-xs monospace"> <a href=/identity/{{ b[6] }}>{{ b[6] }}</a> </td> </td>
<td class="py-3 px-6 text-xs monospace">
<a href=/offer/{{ b[2] }}>{{ b[2]|truncate(20, True) }}</a>
</td>
<td class="py-3 px-6 text-xs monospace">
<a href=/identity/{{ b[6] }}>{{ b[6] }}</a>
</td>
<td class="py-3 px-6 text-xs">{{ b[3] }}</td> <td class="py-3 px-6 text-xs">{{ b[3] }}</td>
<td class="py-3 px-6 text-xs">{{ b[4] }}</td> <td class="py-3 px-6 text-xs">{{ b[4] }}</td>
<td class="py-3 px-6 text-xs">{{ b[5] }}</td> <td class="py-3 px-6 text-xs">{{ b[5] }}</td>
{% if page_type_received or page_type_sent %} {% if page_type_received or page_type_sent %}
<td class="py-3 px-6 text-xs"> <a class="inline-block w-20 py-1 px-2 font-medium text-center text-sm rounded-md bg-blue-500 text-white border border-blue-500 hover:bg-blue-600 transition duration-200 bg-blue-500 text-white hover:bg-blue-600 transition duration-200" href="/bid/{{ b[1] }}">Details</a> <td class="py-3 px-6 text-xs">
</td> {% elif page_type_available %} <a class="inline-block w-20 py-1 px-2 font-medium text-center text-sm rounded-md bg-blue-500 text-white border border-blue-500 hover:bg-blue-600 transition duration-200 bg-blue-500 text-white hover:bg-blue-600 transition duration-200" href="/bid/{{ b[1] }}">Details</a>
<td class="py-3 px-6 text-xs"> <a class="inline-block w-20 py-1 px-2 font-medium text-center text-sm rounded-md bg-blue-500 text-white border border-blue-500 hover:bg-blue-600 transition duration-200 bg-blue-500 text-white hover:bg-blue-600 transition duration-200" href="/bid/{{ b[1] }}">Accept</a> </td>
{% elif page_type_available %}
<td class="py-3 px-6 text-xs">
<a class="inline-block w-20 py-1 px-2 font-medium text-center text-sm rounded-md bg-blue-500 text-white border border-blue-500 hover:bg-blue-600 transition duration-200 bg-blue-500 text-white hover:bg-blue-600 transition duration-200" href="/bid/{{ b[1] }}">Accept</a>
</td> </td>
{% endif %} {% endif %}
</tr> </tr>
</tbody> </tbody>
{% endfor %} {% endfor %}
</table> <input type="hidden" name="formid" value="{{ form_id }}"> <input type="hidden" name="pageno" value="{{ filters.page_no }}"> </table>
<input type="hidden" name="formid" value="{{ form_id }}">
<input type="hidden" name="pageno" value="{{ filters.page_no }}">
</div> </div>
</div> </div>
<div class="rounded-b-md"> <div class="rounded-b-md">
<div class="w-full md:w-0/12"> <div class="w-full md:w-0/12">
<div class="flex flex-wrap justify-end pt-6 pr-6 border-t border-gray-100 dark:border-gray-400"> <div class="flex flex-wrap justify-end pt-6 pr-6 border-t border-gray-100 dark:border-gray-400">
{% if filters.page_no > 1 %} <div class="w-full md:w-auto p-1.5"> <div class="w-full md:w-auto p-1.5">
<button type="submit" name='pageback' value="Previous" class="inline-flex items-center h-9 py-1 px-4 text-xs text-blue-50 font-semibold bg-blue-500 hover:bg-blue-600 rounded-lg transition duration-200 focus:ring-0 focus:outline-none"> <button type="submit" name='pageback' value="Page Back" class="inline-flex items-center h-9 py-1 px-4 text-xs text-blue-50 font-semibold bg-blue-500 hover:bg-blue-600 rounded-lg transition duration-200 focus:ring-0 focus:outline-none">
{{ page_back_svg | safe }} <svg aria-hidden="true" class="mr-2 w-5 h-5" fill="#fff" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<span>Previous</span> <path fill-rule="evenodd" d="M7.707 14.707a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 1.414L5.414 9H17a1 1 0 110 2H5.414l2.293 2.293a1 1 0 010 1.414z" clip-rule="evenodd"></path>
</svg>
<span>Page Back</span>
</button> </button>
</div> </div>
{% endif %}
<div class="flex items-center"> <div class="flex items-center">
<div class="w-full md:w-auto p-1.5"> <div class="w-full md:w-auto p-1.5">
<p class="text-sm font-heading dark:text-white">Page: {{ filters.page_no }}</p> <p class="text-sm font-heading dark:text-white">Page: {{ filters.page_no }}</p>
</div> </div>
</div> </div>
{% if bids_count > 20 %} <div class="w-full md:w-auto p-1.5">
<div class="w-full md:w-auto p-1.5"> <button type="submit" name='pageforwards' value="Next" class="inline-flex items-center h-9 py-1 px-4 text-xs text-blue-50 font-semibold bg-blue-500 hover:bg-blue-600 rounded-lg transition duration-200 focus:ring-0 focus:outline-none"> <button type="submit" name='pageforwards' value="Page Forwards" class="inline-flex items-center h-9 py-1 px-4 text-xs text-blue-50 font-semibold bg-blue-500 hover:bg-blue-600 rounded-lg transition duration-200 focus:ring-0 focus:outline-none">
<span>Next</span> <span>Page Forwards</span>
{{ page_forwards_svg | safe }} <svg aria-hidden="true" class="ml-2 w-5 h-5" fill="#fff" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M12.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-2.293-2.293a1 1 0 010-1.414z" clip-rule="evenodd"></path>
</svg>
</button> </button>
</div> </div>
{% endif %}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,5 +1,4 @@
{% include 'header.html' %} {% include 'header.html' %}
{% from 'style.html' import breadcrumb_line_svg %}
<div class="container mx-auto"> <div class="container mx-auto">
<section class="p-5 mt-5"> <section class="p-5 mt-5">
<div class="flex flex-wrap items-center -m-2"> <div class="flex flex-wrap items-center -m-2">
@@ -10,13 +9,21 @@
<p>Home</p> <p>Home</p>
</a> </a>
</li> </li>
<li>{{ breadcrumb_line_svg | safe }}</li> <li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
<li> <li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/wallets"> <a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/wallets">
<p>Home</p> <p>Home</p>
</a> </a>
</li> </li>
<li>{{ breadcrumb_line_svg | safe }}</li> <li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
<li> <li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/changepassword">Change Password</a> <a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/changepassword">Change Password</a>
</li> </li>
@@ -144,7 +151,13 @@
<div class="px-6"> <div class="px-6">
<div class="flex flex-wrap justify-end"> <div class="flex flex-wrap justify-end">
<div class="w-full md:w-auto p-1.5 ml-2"> <div class="w-full md:w-auto p-1.5 ml-2">
<button type="submit" name="unlock" value="Unlock" 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">Apply</button> <button type="submit" name="unlock" value="Unlock" 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">
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
<polyline points=" 6,12 10,16 18,8 " stroke="#ffffff"></polyline>
<circle cx="12" cy="12" r="11"></circle>
</g>
</svg>Apply </button>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,5 +1,4 @@
{% include 'header.html' %} {% include 'header.html' %}
{% from 'style.html' import breadcrumb_line_svg, start_process_svg %}
<div class="container mx-auto"> <div class="container mx-auto">
<section class="p-5 mt-5"> <section class="p-5 mt-5">
<div class="flex flex-wrap items-center -m-2"> <div class="flex flex-wrap items-center -m-2">
@@ -10,11 +9,19 @@
<p>Home</p> <p>Home</p>
</a> </a>
</li> </li>
<li> {{ breadcrumb_line_svg | safe }} </li> <li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
<li> <li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/debug">Debug</a> <a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/debug">Debug</a>
</li> </li>
<li> {{ breadcrumb_line_svg | safe }} </li> <li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
</ul> </ul>
</div> </div>
</div> </div>
@@ -28,7 +35,7 @@
<div class="relative z-20 flex flex-wrap items-center -m-3"> <div class="relative z-20 flex flex-wrap items-center -m-3">
<div class="w-full md:w-1/2 p-3"> <div class="w-full md:w-1/2 p-3">
<h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">Debug</h2> <h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">Debug</h2>
<p class="font-normal text-coolGray-200 dark:text-white">Expert debug options</p> <p class="font-normal text-coolGray-200 dark:text-white">Debug options & Easter eggs.</p>
</div> </div>
</div> </div>
</div> </div>
@@ -63,15 +70,24 @@
<tr class="opacity-100 text-gray-500 dark:text-gray-100"> <tr class="opacity-100 text-gray-500 dark:text-gray-100">
<td class="py-3 px-6 bold">Remove expired offers and bids</td> <td class="py-3 px-6 bold">Remove expired offers and bids</td>
<td td class="py-3 px-6 "> <td td class="py-3 px-6 ">
<button name="remove_expired" type="submit" value="Yes" class="w-60 flex flex-wrap justify-center py-2 px-4 bg-red-500 hover:bg-red-600 font-medium text-sm text-white border border-red-500 rounded-md shadow-button focus:ring-0 focus:outline-none" onclick="return confirmRemoveExpired();"> <button name="remove_expired" type="submit" value="Yes" class="flex flex-wrap 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" onclick="return confirmRemoveExpired();">
Remove Data</button> Yes - Remove Data</button>
</td> </td>
</tr> </tr>
<tr class="opacity-100 text-gray-500 dark:text-gray-100"> <tr class="opacity-100 text-gray-500 dark:text-gray-100">
<td class="py-3 px-6 bold">Reinitialise XMR wallet</td> <td class="py-3 px-6 bold">Reinitialise XMR wallet</td>
<td td class="py-3 px-6 "> <td td class="py-3 px-6 ">
<button name="reinit_xmr" type="submit" value="Yes" class="w-60 flex flex-wrap 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"> <button name="reinit_xmr" type="submit" value="Yes" class="flex flex-wrap 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">
{{ start_process_svg| safe }} Start Process</button> <svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="square" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="miter" class="nc-icon-wrapper" stroke-miterlimit="10">
<polyline points="2.966 1.13 2.237 6.927 7.929 5.341"></polyline>
<path d="M2.921,18.2a11.006,11.006,0,0,1-1.041-1.9" stroke="#ffffff"></path>
<path d="M8.461,22.412a11.07,11.07,0,0,1-1.529-.654q-.2-.1-.392-.214" stroke="#ffffff"></path>
<path d="M15.539,22.41a11.062,11.062,0,0,1-2.06.486" stroke="#ffffff"></path>
<path d="M21.08,18.206a10.984,10.984,0,0,1-1.438,1.705" stroke="#ffffff"></path>
<path d="M2.759,6.027A11,11,0,0,1,22.9,13.464"></path>
</g>
</svg>Yes - Start Process</button>
</td> </td>
</tr> </tr>
<input type="hidden" name="formid" value="{{ form_id }}"> <input type="hidden" name="formid" value="{{ form_id }}">

View File

@@ -1,5 +1,4 @@
{% include 'header.html' %} {% include 'header.html' %}
{% from 'style.html' import breadcrumb_line_svg, input_arrow_down_svg %}
<div class="container mx-auto"> <div class="container mx-auto">
<section class="p-5 mt-5"> <section class="p-5 mt-5">
<div class="flex flex-wrap items-center -m-2"> <div class="flex flex-wrap items-center -m-2">
@@ -10,11 +9,19 @@
<p>Home</p> <p>Home</p>
</a> </a>
</li> </li>
<li> {{ breadcrumb_line_svg | safe }} </li> <li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
<li> <li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/explores">Explorers</a> <a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/explores">Explorers</a>
</li> </li>
<li> {{ breadcrumb_line_svg | safe }} </li> <li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
</ul> </ul>
</div> </div>
</div> </div>
@@ -55,7 +62,7 @@
</th> </th>
<th class="p-0"> <th class="p-0">
<div class="py-3 px-6 rounded-tr-xl bg-coolGray-200 dark:bg-gray-600"> <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">Action</span> <span class="text-xs text-gray-600 dark:text-gray-300 font-semibold py-3 px-6">Action</span>
</div> </div>
</th> </th>
</tr> </tr>
@@ -63,7 +70,9 @@
<tr class="opacity-100 text-gray-500 dark:text-gray-100"> <tr class="opacity-100 text-gray-500 dark:text-gray-100">
<td class="py-3 px-6"> <td class="py-3 px-6">
<div class="relative"> <div class="relative">
{{ input_arrow_down_svg| safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<select 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" name="explorer"> <select 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" name="explorer">
<!-- <option value="-1" {% if explorer==-1 %} selected{% endif %}>Select Explorer</option> --> <!-- <option value="-1" {% if explorer==-1 %} selected{% endif %}>Select Explorer</option> -->
{% for e in explorers %} {% for e in explorers %}
@@ -73,14 +82,11 @@
</div> </div>
</td> </td>
<td class="py-3 px-6"> <td class="py-3 px-6">
<div class="relative">
{{ input_arrow_down_svg| safe }}
<select 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" name="action"> <select 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" name="action">
<option value="-1" {% if action==-1 %} selected{% endif %}>Select Action</option> <option value="-1" {% if action==-1 %} selected{% endif %}>Select Action</option>
{% for a in actions %} <option value="{{ a[0] }}" {% if action==a[0] %} selected{% endif %}>{{ a[1] }}</option> {% for a in actions %} <option value="{{ a[0] }}" {% if action==a[0] %} selected{% endif %}>{{ a[1] }}</option>
{% endfor %} {% endfor %}
</select> </select>
</div>
</td> </td>
</tr> </tr>
<tr class="opacity-100 text-gray-500 dark:text-gray-100"> <tr class="opacity-100 text-gray-500 dark:text-gray-100">
@@ -109,7 +115,13 @@
<div class="px-6"> <div class="px-6">
<div class="flex flex-wrap justify-end"> <div class="flex flex-wrap justify-end">
<div class="w-full md:w-auto p-1.5 ml-2"> <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">Apply</button> <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">
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
<polyline points=" 6,12 10,16 18,8 " stroke="#ffffff"></polyline>
<circle cx="12" cy="12" r="11"></circle>
</g>
</svg>Apply</button>
</div> </div>
</div> </div>
</div> </div>
@@ -121,13 +133,13 @@
</section> </section>
<input type="hidden" name="formid" value="{{ form_id }}"> <input type="hidden" name="formid" value="{{ form_id }}">
{% if result %} {% if result %}
<section class="rounded-xl"> <section>
<div class="pl-6 pr-6 pt-0 pb-0 h-full overflow-hidden"> <div class="pl-6 pr-6 pt-0 pb-0 h-full overflow-hidden">
<div class="border-coolGray-100"> <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 -m-2">
<div class="w-full pt-2"> <div class="w-full pt-2">
<div class="container mt-5 mx-auto"> <div class="container mt-5 mx-auto">
<div class="pt-6 bg-coolGray-100 dark:bg-gray-500 rounded-xl rounded-bl-none rounded-br-none"> <div class="pt-6 pb-6 bg-coolGray-100 dark:bg-gray-500 rounded-xl">
<div class="px-6"> <div class="px-6">
<div class="w-full mt-6 pb-6 overflow-x-auto"> <div class="w-full mt-6 pb-6 overflow-x-auto">
<table class="w-full min-w-max text-sm"> <table class="w-full min-w-max text-sm">
@@ -142,37 +154,21 @@
</thead> </thead>
<tr class="opacity-100 text-gray-500 dark:text-gray-100"> <tr class="opacity-100 text-gray-500 dark:text-gray-100">
<td class="py-3 px-6"> <td class="py-3 px-6">
<textarea name="result" 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" rows="20">{{ result }}</textarea> <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" rows="20">{{ result }}</textarea>
</td> </td>
</tr> </tr>
</table> </table>
</div> </div>
</div> </div>
{% endif %}
</form> </form>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<section>
<div class="pl-6 pr-6 pt-0 pb-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 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">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
{% endif %}
</div> </div>
{% include 'footer.html' %} {% include 'footer.html' %}
</body> </body>
</html> </html>
<!-- todo round corners -->

View File

@@ -1,4 +1,3 @@
{% from 'style.html' import love_svg, github_svg %}
<section class="overflow-hidden"> <section class="overflow-hidden">
<div class="container px-4 mx-auto"> <div class="container px-4 mx-auto">
<div class="flex flex-wrap lg:items-center pt-24 pb-12 -mx-4"> <div class="flex flex-wrap lg:items-center pt-24 pb-12 -mx-4">
@@ -24,17 +23,27 @@
<div class="flex items-center"> <div class="flex items-center">
<p class="text-sm text-gray-90 dark:text-white font-medium">© 2024~ (BSX) BasicSwap</p> <span class="w-1 h-1 mx-1.5 bg-gray-500 dark:bg-white rounded-full"></span> <p class="text-sm text-gray-90 dark:text-white font-medium">© 2024~ (BSX) BasicSwap</p> <span class="w-1 h-1 mx-1.5 bg-gray-500 dark:bg-white rounded-full"></span>
<p class="text-sm text-coolGray-400 font-medium">BSX: v{{ version }}</p> <span class="w-1 h-1 mx-1.5 bg-gray-500 dark:bg-white rounded-full"></span> <p class="text-sm text-coolGray-400 font-medium">BSX: v{{ version }}</p> <span class="w-1 h-1 mx-1.5 bg-gray-500 dark:bg-white rounded-full"></span>
<p class="text-sm text-coolGray-400 font-medium">GUI: v3.0.0</p> <span class="w-1 h-1 mx-1.5 bg-gray-500 dark:bg-white rounded-full"></span> <p class="text-sm text-coolGray-400 font-medium">GUI: v2.0.3</p> <span class="w-1 h-1 mx-1.5 bg-gray-500 dark:bg-white rounded-full"></span>
<p class="mr-2 text-sm font-bold dark:text-white text-gray-90 ">Made with </p> <p class="mr-2 text-sm font-bold dark:text-white text-gray-90 ">Made with </p>
{{ love_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<span class="ml-2 text-sm font-bold dark:text-white text-gray-90 ">by TV and CRZ</span></div> <g stroke-linecap="round" stroke-width="2" fill="none" stroke="#f80b0b" stroke-linejoin="round">
<path d="M21.243,3.757 c-2.343-2.343-6.142-2.343-8.485,0c-0.289,0.289-0.54,0.6-0.757,0.927c-0.217-0.327-0.469-0.639-0.757-0.927 c-2.343-2.343-6.142-2.343-8.485,0c-2.343,2.343-2.343,6.142,0,8.485L12,21.485l9.243-9.243C23.586,9.899,23.586,6.1,21.243,3.757z"></path>
</g>
</svg> <span class="ml-2 text-sm font-bold dark:text-white text-gray-90 ">by TV and CRZ</span></div>
</div> </div>
</div> </div>
<div class="w-full md:w-1/2"> <div class="w-full md:w-1/2">
<div class="flex flex-wrap md:justify-end -mx-5"> <div class="flex flex-wrap md:justify-end -mx-5">
<div class="px-5"> <div class="px-5">
<a class="inline-block text-coolGray-300 hover:text-coolGray-400" href="https://github.com/tecnovert/basicswap" target="_blank"> <a class="inline-block text-coolGray-300 hover:text-coolGray-400" href="https://github.com/tecnovert/basicswap" target="_blank">
{{ github_svg | safe }} <svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9 0C4.0275 0 0 4.13211 0 9.22838C0 13.3065 2.5785 16.7648 6.15375 17.9841C6.60375 18.0709 6.76875 17.7853 6.76875 17.5403C6.76875 17.3212 6.76125 16.7405 6.7575 15.9712C4.254 16.5277 3.726 14.7332 3.726 14.7332C3.3165 13.6681 2.72475 13.3832 2.72475 13.3832C1.9095 12.8111 2.78775 12.8229 2.78775 12.8229C3.6915 12.887 4.16625 13.7737 4.16625 13.7737C4.96875 15.1847 6.273 14.777 6.7875 14.5414C6.8685 13.9443 7.10025 13.5381 7.3575 13.3073C5.35875 13.0764 3.258 12.2829 3.258 8.74709C3.258 7.73988 3.60675 6.91659 4.18425 6.27095C4.083 6.03774 3.77925 5.0994 4.263 3.82846C4.263 3.82846 5.01675 3.58116 6.738 4.77462C7.458 4.56958 8.223 4.46785 8.988 4.46315C9.753 4.46785 10.518 4.56958 11.238 4.77462C12.948 3.58116 13.7017 3.82846 13.7017 3.82846C14.1855 5.0994 13.8818 6.03774 13.7917 6.27095C14.3655 6.91659 14.7142 7.73988 14.7142 8.74709C14.7142 12.2923 12.6105 13.0725 10.608 13.2995C10.923 13.5765 11.2155 14.1423 11.2155 15.0071C11.2155 16.242 11.2043 17.2344 11.2043 17.5341C11.2043 17.7759 11.3617 18.0647 11.823 17.9723C15.4237 16.7609 18 13.3002 18 9.22838C18 4.13211 13.9703 0 9 0Z" fill="currentColor"></path>
</svg>
</a>
</div>
<div class="px-5">
<a class="inline-block text-coolGray-300 hover:text-coolGray-400" href="#">
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg"></svg>
</a> </a>
</div> </div>
</div> </div>
@@ -42,6 +51,7 @@
</div> </div>
</div> </div>
</section> </section>
<script> <script>
(function() { (function() {
var toggleImages = function() { var toggleImages = function() {
@@ -77,6 +87,9 @@
}); });
})(); })();
</script> </script>
<script> <script>
var themeToggleDarkIcon = document.getElementById('theme-toggle-dark-icon'); var themeToggleDarkIcon = document.getElementById('theme-toggle-dark-icon');
var themeToggleLightIcon = document.getElementById('theme-toggle-light-icon'); var themeToggleLightIcon = document.getElementById('theme-toggle-light-icon');

View File

@@ -1,5 +1,4 @@
<!DOCTYPE html> <!DOCTYPE html>
{% from 'style.html' import notifications_network_offer_svg, notifications_bid_accepted_svg, notifications_unknow_event_svg, notifications_new_bid_on_offer_svg, notifications_close_svg, swap_in_progress_mobile_svg, wallet_svg, page_back_svg, order_book_svg, new_offer_svg, settings_svg, asettings_svg, cog_svg, rpc_svg, debug_svg, explorer_svg, tor_svg, smsg_svg, outputs_svg, automation_svg, shutdown_svg, notifications_svg, debug_nerd_svg, wallet_locked_svg, mobile_menu_svg, wallet_unlocked_svg, tor_purple_svg, sun_svg, moon_svg, swap_in_progress_svg, swap_in_progress_green_svg, available_bids_svg, your_offers_svg, bids_received_svg, bids_sent_svg, header_arrow_down_svg, love_svg %}
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
@@ -92,34 +91,57 @@
<body class="dark:bg-gray-700"> <body class="dark:bg-gray-700">
<section> <section>
<nav class="relative bg-gray-700"> <nav class="relative bg-gray-700">
<div class="p-6 container flex flex-wrap items-center justify-between items-center mx-auto"> <div class="p-6 container flex flex-wrap items-center justify-between items-center mx-auto">
<a class="flex-shrink-0 mr-12 text-2xl text-white font-semibold" href="/"> <img class="h-10" src="/static/images/logos/basicswap-logo.svg" alt="" width="auto"></a> <a class="flex-shrink-0 mr-12 text-2xl text-white font-semibold" href="/"> <img class="h-10" src="/static/images/logos/basicswap-logo.svg" alt="" width="auto"></a>
<ul class="hidden xl:flex"> <ul class="hidden xl:flex">
<li> <li>
<a class="flex mr-10 items-center py-3 text-gray-50 hover:text-gray-100 text-sm" href="/wallets"> <a class="flex mr-10 items-center py-3 text-gray-50 hover:text-gray-100 text-sm" href="/wallets">
{{ wallet_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 24 24">
<span>Wallets</span> <g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
</a> <path d="M6,3H3C1.895,3,1,3.895,1,5 v0c0,1.105,0.895,2,2,2"></path>
<polyline points=" 6,7 6,1 20,1 20,7 " stroke="#6b7280"></polyline>
<path d="M23,7H3 C1.895,7,1,6.105,1,5v15c0,1.657,1.343,3,3,3h19V7z"></path>
<circle cx="17" cy="15" r="2"></circle>
</g>
</svg> <span>Wallets</span></a>
</li> </li>
<li> <li>
<a class="flex mr-10 items-center py-2.5 text-gray-50 hover:text-gray-100 text-sm" href="/offers"> <a class="flex mr-10 items-center py-2.5 text-gray-50 hover:text-gray-100 text-sm" href="/offers">
{{ order_book_svg | safe }}<span>Show Order Book</span> <svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 24 24">
<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_network_offers }}</span> <g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
</a> <rect x="3" y="1" width="18" height="22"></rect>
<line x1="12" y1="8" x2="12" y2="16" stroke="#6b7280"></line>
<line x1="8" y1="14" x2="8" y2="16" stroke="#6b7280"></line>
<line x1="16" y1="11" x2="16" y2="16" stroke="#6b7280"> </line>
</g>
</svg> <span>Show Order Book</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_network_offers }}</span></a>
</li> </li>
<li> <li>
<a class="flex rounded-full flex-wrap justify-center w-full px-4 py-2.5 bg-blue-500 hover:bg-green-600 hover:border-green-600 font-medium text-sm text-white border border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none" href="/newoffer"> <a 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" href="/newoffer">
{{ new_offer_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 24 24">
<span>Place new Offer</span> <g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
</a> <circle cx="5" cy="5" r="4"></circle>
<circle cx="19" cy="19" r="4"></circle>
<polyline data-cap="butt" points="13,5 21,5 21,11 " stroke="#ffffff"></polyline>
<polyline data-cap="butt" points="11,19 3,19 3,13 " stroke="#ffffff"></polyline>
<polyline points=" 16,2 13,5 16,8 " stroke="#ffffff"></polyline>
<polyline points=" 8,16 11,19 8,22 " stroke="#ffffff"></polyline>
</g>
</svg> <span>Place new Offer</span></a>
</li> </li>
</ul> </ul>
<ul class="mr-10 hidden xl:flex lg:justify-end lg:items-center lg:space-x-6 ml-auto"> <ul class="mr-10 hidden xl:flex lg:justify-end lg:items-center lg:space-x-6 ml-auto">
<div id="dropdownNavbarLink" data-dropdown-toggle="dropdownNavbar" class="flex justify-between items-center py-2 pr-4 pl-3 w-full text-gray-50 text-sm md:border-0 md:p-0 md:w-auto text-gray-50 hover:text-gray-100"> <div id="dropdownNavbarLink" data-dropdown-toggle="dropdownNavbar" class="flex justify-between items-center py-2 pr-4 pl-3 w-full text-gray-50 text-sm md:border-0 md:p-0 md:w-auto text-gray-50 hover:text-gray-100">
{{ settings_svg | safe }} Settings & Tools <svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
{{ header_arrow_down_svg| safe }} <g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<path d="M14,19l2.95,2.95A3.5,3.5,0,0,0,21.9,22l.051-.051h0A3.5,3.5,0,0,0,22,17l-.051-.051L20,15" stroke="#6b7280"></path>
<polyline data-cap="butt" points="11.491 8.866 4.203 1.578 1.661 4.12 8.779 11.238" stroke="#6b7280"></polyline>
<path d="M22.678,4.922,19.6,7.987l-3.6-3.576,3.08-3.066a4.214,4.214,0,0,0-2.259-.307,5.615,5.615,0,0,0-5.133,5.723A4.223,4.223,0,0,0,12,8.4L2.145,17.083a3.419,3.419,0,0,0-.276,4.827c.023.027.047.052.071.078h0a3.286,3.286,0,0,0,4.647.1,3.232,3.232,0,0,0,.281-.3l8.726-9.81a6.717,6.717,0,0,0,2.875.2A5.687,5.687,0,0,0,22.78,8.192,5.088,5.088,0,0,0,22.678,4.922Z"></path>
</g>
</svg> Settings & Tools
<svg class="text-gray-400 ml-4" width="10" height="6" viewBox="0 0 10 6" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.08335 0.666657C8.75002 0.333323 8.25002 0.333323 7.91669 0.666657L5.00002 3.58332L2.08335 0.666657C1.75002 0.333323 1.25002 0.333323 0.916687 0.666657C0.583354 0.99999 0.583354 1.49999 0.916687 1.83332L4.41669 5.33332C4.58335 5.49999 4.75002 5.58332 5.00002 5.58332C5.25002 5.58332 5.41669 5.49999 5.58335 5.33332L9.08335 1.83332C9.41669 1.49999 9.41669 0.99999 9.08335 0.666657Z" fill="#6b7280"></path>
</svg>
</div> </div>
</ul> </ul>
<!-- dropdown settings & tools --> <!-- dropdown settings & tools -->
@@ -127,77 +149,138 @@
<ul class="py-0 text-sm text-gray-700" aria-labelledby="dropdownLargeButton"> <ul class="py-0 text-sm text-gray-700" aria-labelledby="dropdownLargeButton">
<li> <li>
<a href="/settings" class="flex items-center block py-4 px-4 hover:bg-gray-100 dark:hover:bg-gray-700 dark:text-white"> <span class="sr-only">Settings</span> <a href="/settings" class="flex items-center block py-4 px-4 hover:bg-gray-100 dark:hover:bg-gray-700 dark:text-white"> <span class="sr-only">Settings</span>
{{ cog_svg | safe }} Settings</a> <svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<circle cx="12" cy="12" r="3" stroke="#6b7280"></circle>
<path d="M20,12a8.049,8.049,0,0,0-.188-1.713l2.714-2.055-2-3.464L17.383,6.094a7.987,7.987,0,0,0-2.961-1.719L14,1H10L9.578,4.375A7.987,7.987,0,0,0,6.617,6.094L3.474,4.768l-2,3.464,2.714,2.055a7.9,7.9,0,0,0,0,3.426L1.474,15.768l2,3.464,3.143-1.326a7.987,7.987,0,0,0,2.961,1.719L10,23h4l.422-3.375a7.987,7.987,0,0,0,2.961-1.719l3.143,1.326,2-3.464-2.714-2.055A8.049,8.049,0,0,0,20,12Z"></path>
</g>
</svg> Settings</a>
</li> </li>
{% if debug_mode == true %} {% if debug_mode == true %}
<li> <li>
<a href="/rpc" class="flex items-center block py-4 px-4 hover:bg-gray-100 dark:hover:bg-gray-700 dark:text-white"> <span class="sr-only">RPC</span> <a href="/rpc" class="flex items-center block py-4 px-4 hover:bg-gray-100 dark:hover:bg-gray-700 dark:text-white"> <span class="sr-only">RPC</span>
{{ rpc_svg | safe }} RPC Console </a> <svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<rect x="1" y="2" width="22" height="20"></rect>
<line x1="1" y1="6" x2="23" y2="6"></line>
<polyline points=" 5,11 7,13 5,15 " stroke="#6b7280"></polyline>
<line x1="10" y1="15" x2="14" y2="15" stroke="#6b7280"></line>
<line x1="6" y1="2" x2="6" y2="6"></line>
</g>
</svg> RPC Console </a>
</li> </li>
{% endif %} {% endif %}
{% if debug_mode == true %} {% if debug_mode == true %}
<li> <li>
<a href="/debug" class="flex items-center block py-4 px-4 hover:bg-gray-100 dark:hover:bg-gray-700 dark:text-white"> <span class="sr-only">Debug</span> <a href="/debug" class="flex items-center block py-4 px-4 hover:bg-gray-100 dark:hover:bg-gray-700 dark:text-white"> <span class="sr-only">Debug</span>
{{ debug_svg | safe }} Debug</a> <svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<path data-cap="butt" d="M5.29,10H4A3,3,0,0,1,1,7V6" stroke="#6b7280"></path>
<path data-cap="butt" d="M5.29,18H4a3,3,0,0,0-3,3v1" stroke="#6b7280"></path>
<path data-cap="butt" d="M8,6.255V5a4,4,0,0,1,4-4h0a4,4,0,0,1,4,4V6.255" stroke="#6b7280"></path>
<line x1="5" y1="14" x2="1" y2="14" stroke="#6b7280"></line>
<path data-cap="butt" d="M18.71,10H20a3,3,0,0,0,3-3V6" stroke="#6b7280"></path>
<path data-cap="butt" d="M18.71,18H20a3,3,0,0,1,3,3v1" stroke="#6b7280"></path>
<line x1="19" y1="14" x2="23" y2="14" stroke="#6b7280"></line>
<path d="M19,16A7,7,0,0,1,5,16V12a7,7,0,0,1,14,0Z"></path>
</g>
</svg> Debug</a>
</li> </li>
{% endif %} {% endif %}
{% if debug_mode == true %} {% if debug_mode == true %}
<li> <li>
<a href="/explorers" class="flex items-center block py-4 px-4 hover:bg-gray-100 dark:hover:bg-gray-700 dark:text-white"> <span class="sr-only">Explorers</span> <a href="/explorers" class="flex items-center block py-4 px-4 hover:bg-gray-100 dark:hover:bg-gray-700 dark:text-white"> <span class="sr-only">Explorers</span>
{{ explorer_svg | safe }} Explorers </a> <svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<line x1="22" y1="22" x2="15.656" y2="15.656" stroke="#6b7280"></line>
<circle cx="10" cy="10" r="8"></circle>
</g>
</svg> Explorers </a>
</li> </li>
{% endif %} {% endif %}
{% if use_tor_proxy == true %} {% if use_tor_proxy == true %}
<li> <li>
<a href="/tor" class="flex items-center block py-4 px-4 hover:bg-gray-100 dark:hover:bg-gray-700 dark:text-white"> <span class="sr-only">Tor</span> <a href="/tor" class="flex items-center block py-4 px-4 hover:bg-gray-100 dark:hover:bg-gray-700 dark:text-white"> <span class="sr-only">Debug</span>
{{ tor_svg | safe }} Tor </a> <svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<path d="M9,18.8A6.455,6.455,0,0,1,7,14,6.455,6.455,0,0,1,9,9.2" stroke="#6b7280"></path>
<path d="M15,18.8A6.455,6.455,0,0,0,17,14a6.455,6.455,0,0,0-2-4.8" stroke="#6b7280"></path>
<path d="M14,2.256V1H10V2.256A3.949,3.949,0,0,1,7.658,5.891,8.979,8.979,0,0,0,2,14c0,4.971,4.477,9,10,9s10-4.029,10-9a8.978,8.978,0,0,0-5.658-8.109A3.95,3.95,0,0,1,14,2.256Z"></path>
</g>
</svg>
</svg> Tor </a>
</li> </li>
{% endif %} {% endif %}
<li> <li>
<a href="/smsgaddresses" class="flex items-center block py-4 px-4 hover:bg-gray-100 dark:hover:bg-gray-700 dark:text-white"> <span class="sr-only">Settings</span> <a href="/smsgaddresses" class="flex items-center block py-4 px-4 hover:bg-gray-100 dark:hover:bg-gray-700 dark:text-white"> <span class="sr-only">Settings</span>
{{ smsg_svg | safe }} SMSG Addresses</a> <svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<path data-cap="butt" d="M11.992,11.737,14.2,13.4A2,2,0,0,1,15,15v1H7V15a2,2,0,0,1,.8-1.6l2.208-1.663" stroke="#6b7280"></path>
<rect x="9" y="7" width="4" height="5" rx="2" ry="2" stroke="#6b7280"></rect>
<path d="M2,1H18a2,2,0,0,1,2,2V21a2,2,0,0,1-2,2H2Z"></path>
<line x1="23" y1="5" x2="23" y2="9" stroke="#6b7280"></line>
</g>
</svg> SMSG Addresses</a>
</li> </li>
<li> <li>
<a href="/watched" class="flex items-center block py-4 px-4 hover:bg-gray-100 dark:hover:bg-gray-700 dark:text-white"> <span class="sr-only">Automation Strategies</span> <a href="/watched" class="flex items-center block py-4 px-4 hover:bg-gray-100 dark:hover:bg-gray-700 dark:text-white"> <span class="sr-only">Automation Strategies</span>
{{ outputs_svg | safe }} Watch Outputs <svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<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_watched_outputs }}</span> <g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
</a> <path d="M1.373,13.183a2.064,2.064,0,0,1,0-2.366C2.946,8.59,6.819,4,12,4s9.054,4.59,10.627,6.817a2.064,2.064,0,0,1,0,2.366C21.054,15.41,17.181,20,12,20S2.946,15.41,1.373,13.183Z"></path>
<circle cx="12" cy="12" r="4" stroke="#6b7280"></circle>
</g>
</svg> Watch Outputs <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_watched_outputs }}</span> </a>
</li> </li>
{% if debug_mode == true %} {% if debug_mode == true %}
<li> <li>
<a href="/automation" class="flex items-center block py-4 px-4 hover:bg-gray-10 dark:hover:bg-gray-700 dark:text-white"> <span class="sr-only">Automation Strategies</span> <a href="/automation" class="flex items-center block py-4 px-4 hover:bg-gray-10 dark:hover:bg-gray-700 dark:text-white"> <span class="sr-only">Automation Strategies</span>
{{ automation_svg | safe }} Automation Strategies</a> <svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<line data-cap="butt" x1="5" y1="1" x2="5" y2="6" stroke="#6b7280"></line>
<line x1="3" y1="1" x2="7" y2="1" stroke="#6b7280"> </line>
<line data-cap="butt" x1="19" y1="1" x2="19" y2="6" stroke="#6b7280"></line>
<line x1="17" y1="1" x2="21" y2="1" stroke="#6b7280"></line>
<rect x="6" y="15" width="12" height="4" stroke="#6b7280"></rect>
<line data-cap="butt" x1="10" y1="19" x2="10" y2="15" stroke="#6b7280"></line>
<line data-cap="butt" x1="14" y1="19" x2="14" y2="15" stroke="#6b7280"></line>
<line x1="6" y1="11" x2="8" y2="11" stroke="#6b7280"></line>
<line x1="16" y1="11" x2="18" y2="11" stroke="#6b7280"> </line>
<polygon points="23 6 5 6 1 6 1 23 23 23 23 6"></polygon>
</g>
</svg> Automation Strategies</a>
</li> </li>
{% endif %} {% endif %}
</ul> </ul>
<div class="text-sm text-gray-700"> <div class="text-sm text-gray-700">
<a href="/shutdown/{{ shutdown_token }}" class="flex items-center block py-4 px-4 hover:bg-gray-100 dark:hover:bg-gray-700 dark:text-white"> <span class="sr-only">Shutdown</span> <a href="/shutdown/{{ shutdown_token }}" class="flex items-center block py-4 px-4 hover:bg-gray-100 dark:hover:bg-gray-700 dark:text-white"> <span class="sr-only">Shutdown</span>
{{ shutdown_svg | safe }} Shutdown </a> <svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<line data-cap="butt" x1="11" y1="10" x2="22" y2="10" stroke="#6b7280"></line>
<polyline points="18 6 22 10 18 14" stroke="#6b7280"></polyline>
<polyline data-cap="butt" points="13 13 13 17 8 17"></polyline>
<polyline data-cap="butt" points="1 2 8 7.016 8 22 1 17 1 2 13 2 13 7"></polyline>
</g>
</svg> Shutdown </a>
</div> </div>
</div> </div>
<!-- dropdown settings & tools --> <!-- dropdown settings & tools -->
<!-- notifications --> <!-- notifications -->
<button id="dropdownNotificationButton" data-dropdown-toggle="dropdownNotification" class="inline-flex items-center text-sm font-medium text-center text-gray-500 focus:outline-none " type="button"> <button id="dropdownNotificationButton" data-dropdown-toggle="dropdownNotification" class="inline-flex items-center text-sm font-medium text-center text-gray-500 focus:outline-none " type="button">
{{ notifications_svg | safe }} <svg class="h-5 w-5" viewBox="0 0 16 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14 11.18V8C13.9986 6.58312 13.4958 5.21247 12.5806 4.13077C11.6655 3.04908 10.3971 2.32615 9 2.09V1C9 0.734784 8.89464 0.48043 8.70711 0.292893C8.51957 0.105357 8.26522 0 8 0C7.73478 0 7.48043 0.105357 7.29289 0.292893C7.10536 0.48043 7 0.734784 7 1V2.09C5.60294 2.32615 4.33452 3.04908 3.41939 4.13077C2.50425 5.21247 2.00144 6.58312 2 8V11.18C1.41645 11.3863 0.910998 11.7681 0.552938 12.2729C0.194879 12.7778 0.00173951 13.3811 0 14V16C0 16.2652 0.105357 16.5196 0.292893 16.7071C0.48043 16.8946 0.734784 17 1 17H4.14C4.37028 17.8474 4.873 18.5954 5.5706 19.1287C6.26819 19.6621 7.1219 19.951 8 19.951C8.8781 19.951 9.73181 19.6621 10.4294 19.1287C11.127 18.5954 11.6297 17.8474 11.86 17H15C15.2652 17 15.5196 16.8946 15.7071 16.7071C15.8946 16.5196 16 16.2652 16 16V14C15.9983 13.3811 15.8051 12.7778 15.4471 12.2729C15.089 11.7681 14.5835 11.3863 14 11.18ZM4 8C4 6.93913 4.42143 5.92172 5.17157 5.17157C5.92172 4.42143 6.93913 4 8 4C9.06087 4 10.0783 4.42143 10.8284 5.17157C11.5786 5.92172 12 6.93913 12 8V11H4V8ZM8 18C7.65097 17.9979 7.30857 17.9045 7.00683 17.7291C6.70509 17.5536 6.45451 17.3023 6.28 17H9.72C9.54549 17.3023 9.29491 17.5536 8.99317 17.7291C8.69143 17.9045 8.34903 17.9979 8 18ZM14 15H2V14C2 13.7348 2.10536 13.4804 2.29289 13.2929C2.48043 13.1054 2.73478 13 3 13H13C13.2652 13 13.5196 13.1054 13.7071 13.2929C13.8946 13.4804 14 13.7348 14 14V15Z" fill="#6b7280"></path>
</svg>
<div class="flex relative"> <div class="flex relative">
<!-- Todo --> <!-- Todo -->
<!-- <div class="inline-flex relative -top-2 right-2 w-3 h-3 bg-green-500 rounded-full border-2 border-gray-800"></div> --> <!-- <div class="inline-flex relative -top-2 right-2 w-3 h-3 bg-green-500 rounded-full border-2 border-gray-800"></div> -->
<!-- Red <div class="inline-flex relative -top-2 right-3 w-3 h-3 bg-red-500 rounded-full border-2 border-white"></div> --> <!-- Red <div class="inline-flex relative -top-2 right-3 w-3 h-3 bg-red-500 rounded-full border-2 border-white"></div> --></div>
<!-- Todo -->
</div>
</button> </button>
<!-- Dropdown menu --> <!-- Dropdown menu -->
<div id="dropdownNotification" class="hidden z-50 w-full max-w-sm bg-white shadow rounded divide-y divide-gray-100 drop-shadow dark:bg-gray-500 dark:divide-gray-400 dark:text-white" aria-labelledby="dropdownNotificationButton"> <div id="dropdownNotification" class="hidden z-50 w-full max-w-sm bg-white shadow rounded divide-y divide-gray-100 drop-shadow dark:bg-gray-500 dark:divide-gray-400 dark:text-white" aria-labelledby="dropdownNotificationButton">
<div class="block py-2 px-4 font-semibold text-center text-gray-700 bg-gray-50 drop-shadow dark:text-white dark:bg-gray-500">Notifications History</div> <div class="block py-2 px-4 font-semibold text-center text-gray-700 bg-gray-50 drop-shadow dark:text-white dark:bg-gray-500">Notifications History</div>
<div class="divide-y divide-gray-100 dark:divide-gray-400"> <div class="divide-y divide-gray-100 dark:divide-gray-400">
{% for entry in notifications %} {% if entry[1] == 1 %} {% for entry in notifications %} {% if entry[1] == 1 %}
<div class="flex py-3 px-4 hover:bg-gray-100 dark:hover:bg-gray-700"> <div class="flex py-3 px-4 hover:bg-gray-100 dark:hover:bg-gray-700">
<div class="inline-flex flex-shrink-0 justify-center items-center w-8 h-8 bg-blue-500 rounded-lg"> <div class="inline-flex flex-shrink-0 justify-center items-center w-8 h-8 bg-blue-500 rounded-lg"><svg class="w-5 h-5" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 24 24"><g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round"><circle cx="5" cy="5" r="4"></circle> <circle cx="19" cy="19" r="4"></circle> <polyline data-cap="butt" points="13,5 21,5 21,11 " stroke="#ffffff"></polyline> <polyline data-cap="butt" points="11,19 3,19 3,13 " stroke="#ffffff"></polyline> <polyline points=" 16,2 13,5 16,8 " stroke="#ffffff"></polyline> <polyline points=" 8,16 11,19 8,22 " stroke="#ffffff"></polyline></g></svg></div>
{{ notifications_network_offer_svg | safe }}
</div>
<div class="pl-3 w-full"> <div class="pl-3 w-full">
<div class="text-gray-500 text-sm mb-1.5"> <span class="font-semibold text-gray-900 dark:text-white"> <div class="text-gray-500 text-sm mb-1.5"> <span class="font-semibold text-gray-900 dark:text-white">
NEW NETWORK <a class="underline text-blue-500" href="/offer/{{ entry[2].offer_id }}">OFFER</a></span> NEW NETWORK <a class="underline text-blue-500" href="/offer/{{ entry[2].offer_id }}">OFFER</a></span>
@@ -209,9 +292,7 @@
</div> </div>
{% elif entry[1] == 2 %} {% elif entry[1] == 2 %}
<div class="flex py-3 px-4 hover:bg-gray-100 dark:hover:bg-gray-700"> <div class="flex py-3 px-4 hover:bg-gray-100 dark:hover:bg-gray-700">
<div class="inline-flex flex-shrink-0 justify-center items-center w-8 h-8 bg-blue-500 rounded-lg"> <div class="inline-flex flex-shrink-0 justify-center items-center w-8 h-8 bg-blue-500 rounded-lg"><svg class="w-5 h-5" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 24 24"><g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round"><rect x="9.843" y="5.379" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -0.7635 13.1569)" width="11.314" height="4.243"></rect> <polyline points="3,23 3,19 15,19 15,23 "></polyline> <line x1="4" y1="15" x2="1" y2="15" stroke="#ffffff"></line> <line x1="5.757" y1="10.757" x2="3.636" y2="8.636" stroke="#ffffff"></line> <line x1="1" y1="23" x2="17" y2="23"></line> <line x1="17" y1="9" x2="23" y2="15"></line></g></svg></div>
{{ notifications_new_bid_on_offer_svg | safe }}
</div>
<div class="pl-3 w-full"> <div class="pl-3 w-full">
<div class="text-gray-500 dark:text-white text-sm mb-1.5"> <span class="font-semibold text-gray-900 dark:text-white"> <div class="text-gray-500 dark:text-white text-sm mb-1.5"> <span class="font-semibold text-gray-900 dark:text-white">
<a class="underline text-blue-500" href="/bid/{{ entry[2].bid_id }}">NEW BID</a> ON <a class="underline text-blue-500" href="/offer/{{ entry[2].offer_id }}">OFFER</a></span> <a class="underline text-blue-500" href="/bid/{{ entry[2].bid_id }}">NEW BID</a> ON <a class="underline text-blue-500" href="/offer/{{ entry[2].offer_id }}">OFFER</a></span>
@@ -223,9 +304,7 @@
</div> </div>
{% elif entry[1] == 3 %} {% elif entry[1] == 3 %}
<div class="flex py-3 px-4 hover:bg-gray-100 dark:hover:bg-gray-700"> <div class="flex py-3 px-4 hover:bg-gray-100 dark:hover:bg-gray-700">
<div class="inline-flex flex-shrink-0 justify-center items-center w-8 h-8 bg-violet-500 rounded-lg"> <div class="inline-flex flex-shrink-0 justify-center items-center w-8 h-8 bg-violet-500 rounded-lg"><svg class="w-5 h-5" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 24 24"><g fill="#ffffff"><path d="M8.5,20a1.5,1.5,0,0,1-1.061-.439L.379,12.5,2.5,10.379l6,6,13-13L23.621,5.5,9.561,19.561A1.5,1.5,0,0,1,8.5,20Z" fill="#ffffff"></path></g></svg></div>
{{ notifications_bid_accepted_svg | safe }}
</div>
<div class="pl-3 w-full"> <div class="pl-3 w-full">
<div class="text-gray-500 text-sm mb-1.5 dark:text-white"> <span class="font-semibold text-gray-900 dark:text-white"> <div class="text-gray-500 text-sm mb-1.5 dark:text-white"> <span class="font-semibold text-gray-900 dark:text-white">
<a class="underline text-blue-500" href="/bid/{{ entry[2].bid_id }}">BID</a> ACCEPTED</span> <a class="underline text-blue-500" href="/bid/{{ entry[2].bid_id }}">BID</a> ACCEPTED</span>
@@ -237,9 +316,7 @@
</div> </div>
{% else %} {% else %}
<div class="flex py-3 px-4 hover:bg-gray-100 dark:hover:bg-gray-700"> <div class="flex py-3 px-4 hover:bg-gray-100 dark:hover:bg-gray-700">
<div class="inline-flex flex-shrink-0 justify-center items-center w-8 h-8 bg-blue-500 rounded-lg"> <div class="inline-flex flex-shrink-0 justify-center items-center w-8 h-8 bg-blue-500 rounded-lg"><svg class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 24 24"><g fill="#ffffff"><path d="M8.5,20a1.5,1.5,0,0,1-1.061-.439L.379,12.5,2.5,10.379l6,6,13-13L23.621,5.5,9.561,19.561A1.5,1.5,0,0,1,8.5,20Z" fill="#ffffff"></path></g></svg></div>
{{ notifications_unknow_event_svg | safe }}
</div>
<div class="pl-3 w-full"> <div class="pl-3 w-full">
<div class="text-gray-500 text-sm mb-1.5 dark:text-white"> <span class="font-semibold text-gray-900 dark:text-white"> <div class="text-gray-500 text-sm mb-1.5 dark:text-white"> <span class="font-semibold text-gray-900 dark:text-white">
UNKNOWN EVENT</span> UNKNOWN EVENT</span>
@@ -251,19 +328,36 @@
{% endif %} {% endif %}
{% endfor %} {% endfor %}
</div> </div>
<!-- todo <a href="#" class="block py-2 text-sm font-medium text-center text-gray-900 bg-gray-50 hover:bg-gray-100">
<div class="inline-flex items-center ">
<svg class="mr-2 w-4 h-4 text-gray-500" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<path d="M1.373,13.183a2.064,2.064,0,0,1,0-2.366C2.946,8.59,6.819,4,12,4s9.054,4.59,10.627,6.817a2.064,2.064,0,0,1,0,2.366C21.054,15.41,17.181,20,12,20S2.946,15.41,1.373,13.183Z"></path>
<circle cx="12" cy="12" r="4" stroke="#6b7280"></circle>
</g>
</svg> View all
</div>
</a>-->
</div> </div>
<!-- notifications --> <!-- notifications -->
<!-- todo - fix line -->
<div class="flex mr-2 items-center text-gray-50 hover:text-gray-100 text-sm ml-5"> <div class="flex mr-2 items-center text-gray-50 hover:text-gray-100 text-sm ml-5">
<div class="flex-shrink-0 w-px h-10 bg-gray-400 dark:bg-gray-400 ml-4 mr-5"></div> <div class="flex-shrink-0 w-px h-10 bg-gray-400 dark:bg-gray-400 ml-4 mr-5"></div>
{% if debug_mode == true %} {% if debug_mode == true %}
<!-- dev mode icons on/off --> <!-- dev mode icons on/off -->
<ul class="xl:flex"> <ul class="xl:flex">
<li> <li>
<div data-tooltip-target="tooltip-debug" class="ml-5 flex items-center text-gray-50 hover:text-gray-100 text-sm"> <div data-tooltip-target="tooltip-DEV" class="ml-5 flex items-center text-gray-50 hover:text-gray-100 text-sm">
{{ debug_nerd_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#2ad167" stroke-linejoin="round">
<circle cx="12" cy="12" r="11"></circle>
<path data-cap="butt" d="M9,16a3,3,0,0,0,6,0" stroke="#2ad167"></path>
<circle cx="17" cy="10" r="3" stroke="#2ad167"></circle>
<circle cx="7" cy="10" r="3" stroke="#2ad167"></circle>
<path data-cap="butt" d="M10,10a2,2,0,0,1,4,0" stroke="#2ad167"></path></g>
</svg>
<span data-tooltip-target="tooltip-DEV" ></span> </div> <span data-tooltip-target="tooltip-DEV" ></span> </div>
<div id="tooltip-debug" 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-DEV" 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>Debug mode:</b> Active</p> <p><b>Debug mode:</b> Active</p>
{% if debug_ui_mode == true %} {% if debug_ui_mode == true %}
<p><b>Debug UI mode:</b> Active</p> <p><b>Debug UI mode:</b> Active</p>
@@ -278,7 +372,7 @@
<ul class="xl:flex"><li> <ul class="xl:flex"><li>
{% if locked == true %} {% if locked == true %}
<div data-tooltip-target="tooltip-locked-wallets" class="ml-5 flex items-center text-gray-50 hover:text-gray-100 text-sm"> <div data-tooltip-target="tooltip-locked-wallets" class="ml-5 flex items-center text-gray-50 hover:text-gray-100 text-sm">
{{ wallet_locked_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24"><g stroke-linecap="round" stroke-width="2" fill="none" stroke="#2ad167" stroke-linejoin="round"><rect x="3" y="11" width="18" height="12" rx="2"></rect><circle cx="12" cy="17" r="2" stroke="#2ad167"></circle><path d="M17,7V6a4.951,4.951,0,0,0-4.9-5H12A4.951,4.951,0,0,0,7,5.9V7" stroke="#2ad167"></path></g></svg>
<span data-tooltip-target="tooltip-locked-wallets" ></span> </div> <span data-tooltip-target="tooltip-locked-wallets" ></span> </div>
<div id="tooltip-locked-wallets" 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-locked-wallets" 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>Wallets:</b> Locked </p> <p><b>Wallets:</b> Locked </p>
@@ -286,7 +380,7 @@
{% else %} {% else %}
<a href='/lock'> <a href='/lock'>
<div data-tooltip-target="tooltip-unlocked-wallets" class="ml-5 flex items-center text-gray-50 hover:text-gray-100 text-sm"> <div data-tooltip-target="tooltip-unlocked-wallets" class="ml-5 flex items-center text-gray-50 hover:text-gray-100 text-sm">
{{ wallet_unlocked_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24"><g stroke-linecap="round" stroke-width="2" fill="none" stroke="#f80b0b" stroke-linejoin="round"><rect x="3" y="11" width="18" height="12"></rect><circle cx="12" cy="17" r="2" stroke="#f80b0b"></circle><path data-cap="butt" d="M17,6a4.951,4.951,0,0,0-4.9-5H12A4.951,4.951,0,0,0,7,5.9V11"></path></g></svg>
<span data-tooltip-target="tooltip-unlocked-wallets" ></span> </div> <span data-tooltip-target="tooltip-unlocked-wallets" ></span> </div>
<div class="tooltip-arrow" data-popper-arrow></div> <div class="tooltip-arrow" data-popper-arrow></div>
<div id="tooltip-unlocked-wallets" 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-unlocked-wallets" 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">
@@ -301,60 +395,68 @@
<ul class="xl:flex ml-5"> <ul class="xl:flex ml-5">
<li> <li>
<a href="/tor"> <a href="/tor">
<div data-tooltip-target="tooltip-tor" class="flex items-center text-gray-50 hover:text-gray-100 text-sm"> <div data-tooltip-target="tooltip-TOR" class="flex items-center text-gray-50 hover:text-gray-100 text-sm">
{{ tor_purple_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
</a> <span data-tooltip-target="tooltip-tor"></span></div> <g stroke-linecap="round" stroke-width="2" fill="none" stroke="#AA70E4" stroke-linejoin="round">
<div id="tooltip-tor" 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"><b>Tor mode:</b> Active <path d="M9,18.8A6.455,6.455,0,0,1,7,14,6.455,6.455,0,0,1,9,9.2" stroke="#AA70E4"></path>
{% if tor_established == true %} <path d="M15,18.8A6.455,6.455,0,0,0,17,14a6.455,6.455,0,0,0-2-4.8" stroke="#AA70E4"></path>
<br><b>Tor:</b> Connected <path d="M14,2.256V1H10V2.256A3.949,3.949,0,0,1,7.658,5.891,8.979,8.979,0,0,0,2,14c0,4.971,4.477,9,10,9s10-4.029,10-9a8.978,8.978,0,0,0-5.658-8.109A3.95,3.95,0,0,1,14,2.256Z"></path>
{% endif %} </g>
</div> </svg>
</a> <span data-tooltip-target="tooltip-TOR"></span></div>
<div id="tooltip-TOR" 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"><b>Tor mode:</b> Active {% if tor_established == true %}
<br><b>Tor:</b> Connected{% endif %}</div>
</li> </li>
</ul> </ul>
<!-- tor --> <!-- tor -->
{% endif %} {% endif %}
<button data-tooltip-target="tooltip-darkmode" id="theme-toggle" type="button" class="text-gray-500 dark:text-gray-400 focus:outline-none rounded-lg text-sm ml-5"> <button data-tooltip-target="tooltip-darkmode" id="theme-toggle" type="button" class="text-gray-500 dark:text-gray-400 focus:outline-none rounded-lg text-sm ml-5">
{{ sun_svg | safe }} <svg id="theme-toggle-dark-icon" class="hidden w-5 h-5" fill="#F59E0B" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"></path></svg>
{{ moon_svg | safe }} <svg id="theme-toggle-light-icon" class="hidden w-5 h-5" fill="#F59E0B" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>
<span data-tooltip-target="tooltip-darkmode"></span> <span data-tooltip-target="tooltip-darkmode"></span>
<div id="tooltip-darkmode" 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">Dark mode</div> <div id="tooltip-darkmode" 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">Dark mode</div>
</button> </button>
</div> </div>
<div class="hidden xl:block"></div> <div class="hidden xl:block"></div>
<!-- mobile menu --> <!-- mobile menu -->
<div class="ml-auto flex xl:hidden"> <div class="ml-auto flex xl:hidden">
<button class="navbar-burger flex items-center rounded focus:outline-none"> <button class="navbar-burger flex items-center rounded focus:outline-none">
{{ mobile_menu_svg | safe }} <svg class="text-white bg-blue-500 hover:bg-blue-600 block h-8 w-8 p-2 rounded" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" fill="currentColor">
<title>Mobile Menu</title>
<path d="M0 3h20v2H0V3zm0 6h20v2H0V9zm0 6h20v2H0v-2z"></path>
</svg>
</button> </button>
</div> </div>
<!-- mobile menu -->
</div> </div>
<div class="hidden xl:block py-5 px-6 bg-coolGray-100 border-gray-100 dark:border-gray-500 dark:bg-body border-b dark:border-b-2"> <div class="hidden xl:block py-5 px-6 bg-coolGray-100 border-gray-100 dark:border-gray-500 dark:bg-body border-b dark:border-b-2">
<div class="flex items-center container flex flex-wrap items-center justify-between items-center mx-auto"> <div class="flex items-center container flex flex-wrap items-center justify-between items-center mx-auto">
<ul class="flex items-center"> <ul class="flex items-center">
<li> <li>
<a class="flex mr-5 items-center text-sm text-gray-400 hover:text-gray-600 dark:text-gray-100 dark:hover:text-gray-100" href="/active"> <a class="flex mr-5 items-center text-sm text-gray-400 hover:text-gray-600 dark:text-gray-100 dark:hover:text-gray-100" href="/active">
<div id="swapContainer" class="inline-flex center-spin ml-7 mr-2" {% if summary.num_swapping != 0 %}style="animation: spin 2s linear infinite;"{% endif %}> <svg class="text-gray-100 w-5 h-5 ml-7 mr-2" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
{% if summary.num_swapping != 0 %} <g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
{{ swap_in_progress_green_svg | safe }} <circle data-cap="butt" cx="12" cy="12" r="3" stroke="#6b7280"></circle>
{% else %} <polyline points="16.071 5.341 21.763 6.927 21.034 1.13"></polyline>
{{ swap_in_progress_svg | safe }} <path data-cap="butt" d="M1,12A11,11,0,0,1,21.763,6.927"></path>
{% endif %} <polyline points="7.929 18.659 2.237 17.073 2.966 22.87"></polyline>
</div> <path data-cap="butt" d="M23,12A11,11,0,0,1,2.237,17.073"></path>
<span>Swaps in Progress</span> </g>
<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 num-swap">{{ summary.num_swapping }}</span> </svg><span>Swaps in Progress </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_swapping }}</span></a>
</a>
</li> </li>
<div class="flex-shrink-0 w-px h-10 bg-gray-200 dark:bg-gray-400 mr-10"></div> <div class="flex-shrink-0 w-px h-10 bg-gray-200 dark:bg-gray-400 mr-10"></div>
<li> <li>
<a data-tooltip-target="tooltip-your-offers" class="flex mr-5 items-center text-sm text-gray-400 hover:text-gray-600 dark:text-gray-100 dark:hover:text-gray-100" href="/sentoffers"> <a data-tooltip-target="tooltip-your-offers" class="flex mr-5 items-center text-sm text-gray-400 hover:text-gray-600 dark:text-gray-100 dark:hover:text-gray-100" href="/sentoffers">
{{ your_offers_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 24 24">
<span>Your Offers</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_offers }}</span></a> <g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<circle cx="5" cy="5" r="4"></circle>
<circle cx="19" cy="19" r="4"></circle>
<polyline data-cap="butt" points="13,5 21,5 21,11 " stroke="#6b7280"></polyline>
<polyline data-cap="butt" points="11,19 3,19 3,13 " stroke="#6b7280"></polyline>
<polyline points=" 16,2 13,5 16,8 " stroke="#6b7280"></polyline>
<polyline points=" 8,16 11,19 8,22 " stroke="#6b7280"></polyline>
</g>
</svg><span>Your Offers</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_offers }}</span></a>
<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"> <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> <p><b>Total:</b> {{ summary.num_sent_offers }}</p>
@@ -364,13 +466,23 @@
</li> </li>
<div class="flex-shrink-0 w-px h-10 bg-gray-200 dark:bg-gray-400 mr-10"></div> <div class="flex-shrink-0 w-px h-10 bg-gray-200 dark:bg-gray-400 mr-10"></div>
<li> <li>
<a 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="/availablebids">{{ available_bids_svg | safe }} <a 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="/availablebids">
<span>Available Bids</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_available_bids }}</span></a> <svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<circle cx="12" cy="12" r="11"></circle>
<polyline points=" 12,6 12,12 18,12 " stroke="#6b7280"></polyline>
</g>
</svg><span>Available Bids</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_available_bids }}</span></a>
</li> </li>
<li> <li>
<a data-tooltip-target="tooltip-bids-received" 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="/receivedbids"> <a data-tooltip-target="tooltip-bids-received" 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="/receivedbids">
{{ bids_received_svg | safe }} <svg class="text-gray-100 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<span>Bids Received</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_recv_active_bids }}</span></a> <g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<path d="M2,16v4a2,2,0,0,0,2,2H20a2,2,0,0,0,2-2V16"> </path>
<line data-cap="butt" x1="12" y1="1" x2="12" y2="16" stroke="#6b7280"></line>
<polyline points="7 11 12 16 17 11" stroke="#6b7280"></polyline>
</g>
</svg><span>Bids Received</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_recv_active_bids }}</span></a>
</li> </li>
<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"> <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">
@@ -379,8 +491,13 @@
</div> </div>
<li> <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"> <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">
{{ bids_sent_svg| safe }} <svg class="text-gray-100 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<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> <g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<path d="M2,16v4a2,2,0,0,0,2,2H20a2,2,0,0,0,2-2V16"></path>
<line data-cap="butt" x1="12" y1="17" x2="12" y2="2" stroke="#6b7280"></line>
<polyline points="17 7 12 2 7 7" stroke="#6b7280"></polyline>
</g>
</svg><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"> <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> <p><b>Total:</b> {{ summary.num_sent_bids }}</p>
<div class="tooltip-arrow" data-popper-arrow></div> <div class="tooltip-arrow" data-popper-arrow></div>
@@ -403,46 +520,103 @@
<ul class="mb-8 text-sm font-medium"> <ul class="mb-8 text-sm font-medium">
<li> <li>
<a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/wallets"> <span class="inline-block mr-3"> <a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/wallets"> <span class="inline-block mr-3">
{{ wallet_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 24 24">
</span><span>Wallets</span> <g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<span class="inline-block ml-auto"></span></a> <path d="M6,3H3C1.895,3,1,3.895,1,5 v0c0,1.105,0.895,2,2,2"></path>
<polyline points=" 6,7 6,1 20,1 20,7 " stroke="#6b7280"></polyline>
<path d="M23,7H3 C1.895,7,1,6.105,1,5v15c0,1.657,1.343,3,3,3h19V7z"></path>
<circle cx="17" cy="15" r="2"></circle>
</g>
</svg>
</span><span>Wallets</span> <span class="inline-block ml-auto">
</span></a>
</li> </li>
</ul> </ul>
<h3 class="mb-2 text-xs uppercase text-gray-300 font-medium dark:text-gray-300">Exchange</h3> <h3 class="mb-2 text-xs uppercase text-gray-300 font-medium dark:text-gray-300">Exchange</h3>
<ul class="text-sm font-medium"> <ul class="text-sm font-medium">
<li> <li>
<a class="flex items-center pl-3 py-3 pr-2 text-gray-50 hover:bg-gray-900 rounded" href="/newoffer"> <span class="inline-block mr-3"> <a class="flex items-center pl-3 py-3 pr-2 text-gray-50 hover:bg-gray-900 rounded" href="/newoffer"> <span class="inline-block mr-3">
{{ new_offer_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<circle cx="5" cy="5" r="4"></circle>
<circle cx="19" cy="19" r="4"></circle>
<polyline data-cap="butt" points="13,5 21,5 21,11 " stroke="#6b7280"></polyline>
<polyline data-cap="butt" points="11,19 3,19 3,13 " stroke="#6b7280"></polyline>
<polyline points=" 16,2 13,5 16,8 " stroke="#6b7280"></polyline>
<polyline points=" 8,16 11,19 8,22 " stroke="#6b7280"></polyline>
</g>
</svg>
</span><span>Place new Offer</span></a> </span><span>Place new Offer</span></a>
</li> </li>
<li> <li>
<a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/active"> <span class="inline-block mr-3"> <a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/active"> <span class="inline-block mr-3">
{{ swap_in_progress_mobile_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<circle data-cap="butt" cx="12" cy="12" r="3" stroke="#6b7280"></circle>
<polyline points="16.071 5.341 21.763 6.927 21.034 1.13"></polyline>
<path data-cap="butt" d="M1,12A11,11,0,0,1,21.763,6.927"></path>
<polyline points="7.929 18.659 2.237 17.073 2.966 22.87"></polyline>
<path data-cap="butt" d="M23,12A11,11,0,0,1,2.237,17.073"></path>
</g>
</svg>
</span><span>Swaps in Progress</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_swapping }}</span></a> </span><span>Swaps in Progress</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_swapping }}</span></a>
</li> </li>
<li> <li>
<a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/offers"> <span class="inline-block mr-3"> <a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/offers"> <span class="inline-block mr-3">
{{ order_book_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<rect x="3" y="1" width="18" height="22"></rect>
<line x1="12" y1="8" x2="12" y2="16" stroke="#6b7280"></line>
<line x1="8" y1="14" x2="8" y2="16" stroke="#6b7280"></line>
<line x1="16" y1="11" x2="16" y2="16" stroke="#6b7280"> </line>
</g>
</svg>
</span><span>Show Order Book</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_network_offers }}</span></a> </span><span>Show Order Book</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_network_offers }}</span></a>
</li> </li>
<li> <li>
<a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="sentoffers"> <span class="inline-block mr-3"> <a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="sentoffers"> <span class="inline-block mr-3">
{{ your_offers_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<circle cx="5" cy="5" r="4"></circle>
<circle cx="19" cy="19" r="4"></circle>
<polyline data-cap="butt" points="13,5 21,5 21,11 " stroke="#6b7280"></polyline>
<polyline data-cap="butt" points="11,19 3,19 3,13 " stroke="#6b7280"></polyline>
<polyline points=" 16,2 13,5 16,8 " stroke="#6b7280"></polyline>
<polyline points=" 8,16 11,19 8,22 " stroke="#6b7280"></polyline>
</g>
</svg>
</span><span>Your Offers</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_offers }}</span></a> </span><span>Your Offers</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_offers }}</span></a>
</li> </li>
<li> <li>
<a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/availablebids"> <span class="inline-block mr-3"> <a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/availablebids"> <span class="inline-block mr-3">
{{ available_bids_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<circle cx="12" cy="12" r="11"></circle>
<polyline points=" 12,6 12,12 18,12 " stroke="#6b7280"></polyline>
</g>
</svg>
</span><span>Available Bids</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_available_bids }}</span></a> </span><span>Available Bids</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_available_bids }}</span></a>
</li> </li>
<li> <li>
<a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/receivedbids"> <span class="inline-block mr-3"> <a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/receivedbids"> <span class="inline-block mr-3">
{{ bids_received_svg | safe }} <svg class="text-gray-100 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<path d="M2,16v4a2,2,0,0,0,2,2H20a2,2,0,0,0,2-2V16"> </path>
<line data-cap="butt" x1="12" y1="1" x2="12" y2="16" stroke="#6b7280"></line>
<polyline points="7 11 12 16 17 11" stroke="#6b7280"></polyline>
</g>
</svg>
</span><span>Bids Received</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_recv_bids }}</span></a> </span><span>Bids Received</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_recv_bids }}</span></a>
</li> </li>
<li> <li>
<a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/sentbids"> <span class="inline-block mr-3"> <a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/sentbids"> <span class="inline-block mr-3">
{{ bids_sent_svg | safe }} <svg class="text-gray-100 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<path d="M2,16v4a2,2,0,0,0,2,2H20a2,2,0,0,0,2-2V16"></path>
<line data-cap="butt" x1="12" y1="17" x2="12" y2="2" stroke="#6b7280"></line>
<polyline points="17 7 12 2 7 7" stroke="#6b7280"></polyline>
</g>
</svg>
</span><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_bids }}</span></a> </span><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_bids }}</span></a>
</li> </li>
</ul> </ul>
@@ -450,65 +624,127 @@
<ul class="text-sm font-medium"> <ul class="text-sm font-medium">
<li> <li>
<a class="flex items-center pl-3 py-3 pr-2 text-gray-50 hover:bg-gray-900 rounded" href="/settings"> <span class="inline-block mr-3"> <a class="flex items-center pl-3 py-3 pr-2 text-gray-50 hover:bg-gray-900 rounded" href="/settings"> <span class="inline-block mr-3">
{{ settings_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<circle cx="12" cy="12" r="3" stroke="#6b7280"></circle>
<path d="M20,12a8.049,8.049,0,0,0-.188-1.713l2.714-2.055-2-3.464L17.383,6.094a7.987,7.987,0,0,0-2.961-1.719L14,1H10L9.578,4.375A7.987,7.987,0,0,0,6.617,6.094L3.474,4.768l-2,3.464,2.714,2.055a7.9,7.9,0,0,0,0,3.426L1.474,15.768l2,3.464,3.143-1.326a7.987,7.987,0,0,0,2.961,1.719L10,23h4l.422-3.375a7.987,7.987,0,0,0,2.961-1.719l3.143,1.326,2-3.464-2.714-2.055A8.049,8.049,0,0,0,20,12Z"></path>
</g>
</svg>
</span><span>Settings</span></a> </span><span>Settings</span></a>
</li> </li>
{% if debug_mode == true %} {% if debug_mode == true %}
<li> <li>
<a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/rpc"> <span class="inline-block mr-3"> <a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/rpc"> <span class="inline-block mr-3">
{{ rpc_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<rect x="1" y="2" width="22" height="20"></rect>
<line x1="1" y1="6" x2="23" y2="6"></line>
<polyline points=" 5,11 7,13 5,15 " stroke="#6b7280"></polyline>
<line x1="10" y1="15" x2="14" y2="15" stroke="#6b7280"></line>
<line x1="6" y1="2" x2="6" y2="6"></line>
</g>
</svg>
</span><span>RPC Console</span></a> </span><span>RPC Console</span></a>
</li> </li>
{% endif %} {% endif %}
{% if debug_mode == true %} {% if debug_mode == true %}
<li> <li>
<a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/debug"> <span class="inline-block mr-3"> <a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/debug"> <span class="inline-block mr-3">
{{ debug_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<path data-cap="butt" d="M5.29,10H4A3,3,0,0,1,1,7V6" stroke="#6b7280"></path>
<path data-cap="butt" d="M5.29,18H4a3,3,0,0,0-3,3v1" stroke="#6b7280"></path>
<path data-cap="butt" d="M8,6.255V5a4,4,0,0,1,4-4h0a4,4,0,0,1,4,4V6.255" stroke="#6b7280"></path>
<line x1="5" y1="14" x2="1" y2="14" stroke="#6b7280"></line> <path data-cap="butt" d="M18.71,10H20a3,3,0,0,0,3-3V6" stroke="#6b7280"></path>
<path data-cap="butt" d="M18.71,18H20a3,3,0,0,1,3,3v1" stroke="#6b7280"></path> <line x1="19" y1="14" x2="23" y2="14" stroke="#6b7280"></line>
<path d="M19,16A7,7,0,0,1,5,16V12a7,7,0,0,1,14,0Z"></path></g></svg>
</span> <span>Debug</span> </a> </span> <span>Debug</span> </a>
</li> </li>
{% endif %} {% endif %}
{% if debug_mode == true %} {% if debug_mode == true %}
<li> <li>
<a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/explorers"> <span class="inline-block mr-3"> <a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/explorers"> <span class="inline-block mr-3">
{{ explorer_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<line x1="22" y1="22" x2="15.656" y2="15.656" stroke="#6b7280"></line>
<circle cx="10" cy="10" r="8"></circle>
</g>
</svg>
</span><span>Explorers</span></a> </span><span>Explorers</span></a>
</li> </li>
{% endif %} {% endif %}
<li> <li>
<a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/smsgaddresses"> <span class="inline-block mr-3"> <a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/smsgaddresses"> <span class="inline-block mr-3">
{{ smsg_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<path data-cap="butt" d="M11.992,11.737,14.2,13.4A2,2,0,0,1,15,15v1H7V15a2,2,0,0,1,.8-1.6l2.208-1.663" stroke="#6b7280"></path>
<rect x="9" y="7" width="4" height="5" rx="2" ry="2" stroke="#6b7280"></rect>
<path d="M2,1H18a2,2,0,0,1,2,2V21a2,2,0,0,1-2,2H2Z"></path>
<line x1="23" y1="5" x2="23" y2="9" stroke="#6b7280"></line>
</g>
</svg>
</span><span>SMSG Addresses</span></a> </span><span>SMSG Addresses</span></a>
</li> </li>
<li> <li>
<a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/watched"> <span class="inline-block mr-3"> <a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/watched"> <span class="inline-block mr-3">
{{ outputs_svg| safe }} <svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<path d="M1.373,13.183a2.064,2.064,0,0,1,0-2.366C2.946,8.59,6.819,4,12,4s9.054,4.59,10.627,6.817a2.064,2.064,0,0,1,0,2.366C21.054,15.41,17.181,20,12,20S2.946,15.41,1.373,13.183Z"></path>
<circle cx="12" cy="12" r="4" stroke="#6b7280"></circle>
</g>
</svg>
</span><span>Watched Outputs</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_watched_outputs }}</span></a> </span><span>Watched Outputs</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_watched_outputs }}</span></a>
</li> </li>
{% if debug_mode == true %} {% if debug_mode == true %}
<li> <li>
<a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/automation"> <span class="inline-block mr-3"> <a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/automation"> <span class="inline-block mr-3">
{{ automation_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<line data-cap="butt" x1="5" y1="1" x2="5" y2="6" stroke="#6b7280"></line>
<line x1="3" y1="1" x2="7" y2="1" stroke="#6b7280"> </line>
<line data-cap="butt" x1="19" y1="1" x2="19" y2="6" stroke="#6b7280"></line>
<line x1="17" y1="1" x2="21" y2="1" stroke="#6b7280"></line>
<rect x="6" y="15" width="12" height="4" stroke="#6b7280"></rect>
<line data-cap="butt" x1="10" y1="19" x2="10" y2="15" stroke="#6b7280"></line>
<line data-cap="butt" x1="14" y1="19" x2="14" y2="15" stroke="#6b7280"></line>
<line x1="6" y1="11" x2="8" y2="11" stroke="#6b7280"></line>
<line x1="16" y1="11" x2="18" y2="11" stroke="#6b7280"> </line>
<polygon points="23 6 5 6 1 6 1 23 23 23 23 6"></polygon>
</g>
</svg>
</span><span>Automation Strategies</span></a> </span><span>Automation Strategies</span></a>
</li> </li>
{% endif %} {% endif %}
{% if use_tor_proxy == true %} {% if use_tor_proxy == true %}
<li> <li>
<a class="flex items-center pl-3 py-3 pr-2 text-gray-50 hover:bg-gray-900 rounded" href="/tor"> <span class="inline-block mr-3"> <a class="flex items-center pl-3 py-3 pr-2 text-gray-50 hover:bg-gray-900 rounded" href="/tor"> <span class="inline-block mr-3">
{{ tor_svg | safe }} <!-- change color --> <svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#AA70E4" stroke-linejoin="round">
<path d="M9,18.8A6.455,6.455,0,0,1,7,14,6.455,6.455,0,0,1,9,9.2" stroke="#AA70E4"></path>
<path d="M15,18.8A6.455,6.455,0,0,0,17,14a6.455,6.455,0,0,0-2-4.8" stroke="#AA70E4"></path>
<path d="M14,2.256V1H10V2.256A3.949,3.949,0,0,1,7.658,5.891,8.979,8.979,0,0,0,2,14c0,4.971,4.477,9,10,9s10-4.029,10-9a8.978,8.978,0,0,0-5.658-8.109A3.95,3.95,0,0,1,14,2.256Z"></path>
</g>
</svg>
</span><span>Tor</span></a> </span><span>Tor</span></a>
</li> </li>
{% endif %} {% endif %}
</ul> </ul>
<div class="pt-8 text-sm font-medium"> <div class="pt-8 text-sm font-medium">
<a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/shutdown/{{ shutdown_token }}"> <span class="inline-block mr-3"> <a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/shutdown/{{ shutdown_token }}"> <span class="inline-block mr-3">
{{ shutdown_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<line data-cap="butt" x1="11" y1="10" x2="22" y2="10" stroke="#6b7280"></line>
<polyline points="18 6 22 10 18 14" stroke="#6b7280"></polyline>
<polyline data-cap="butt" points="13 13 13 17 8 17"></polyline>
<polyline data-cap="butt" points="1 2 8 7.016 8 22 1 17 1 2 13 2 13 7"></polyline>
</g>
</svg>
</span><span>Shutdown</span></a> </span><span>Shutdown</span></a>
</div> </div>
</div> </div>
</nav> </nav>
</div> </div>
<!-- mobile sidebar --> <!-- mobile sidebar -->
</section> </section>
{% if ws_url %} {% if ws_url %}
<script> <script>

View File

@@ -1,5 +1,4 @@
{% include 'header.html' %} {% include 'header.html' %}
{% from 'style.html' import breadcrumb_line_svg, red_cross_close_svg %}
<div class="container mx-auto"> <div class="container mx-auto">
<section class="p-5 mt-5"> <section class="p-5 mt-5">
<div class="flex flex-wrap items-center -m-2"> <div class="flex flex-wrap items-center -m-2">
@@ -10,13 +9,21 @@
<p>Home</p> <p>Home</p>
</a> </a>
</li> </li>
<li>{{ breadcrumb_line_svg | safe }}</li> <li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
<li> <li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/smsgaddresses">Identity</a> <a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/smsgaddresses">Identity</a>
</li> </li>
<li>{{ breadcrumb_line_svg | safe }}</li>
<li> <li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/identity/{{ data.identity_address }}">Address: {{ data.identity_address }}</a> <svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
<li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/identity/{{ data.identity_address }}">ADDRESS: {{ data.identity_address }}</a>
</li> </li>
</ul> </ul>
</div> </div>
@@ -31,7 +38,7 @@
<div class="relative z-20 flex flex-wrap items-center -m-3"> <div class="relative z-20 flex flex-wrap items-center -m-3">
<div class="w-full md:w-1/2 p-3"> <div class="w-full md:w-1/2 p-3">
<h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">Identity</h2> <h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">Identity</h2>
<p class="font-normal text-coolGray-200 dark:text-white"><span class="bold">Address:</span> {{ data.identity_address }}</p> <p class="font-normal text-coolGray-200 dark:text-white">Address: {{ data.identity_address }}</p>
</div> </div>
</div> </div>
</div> </div>
@@ -146,14 +153,34 @@
<div class="flex flex-wrap justify-end"> <div class="flex flex-wrap justify-end">
{% if data.show_edit_form %} {% if data.show_edit_form %}
<div class="w-full md:w-auto p-1.5 ml-2"> <div class="w-full md:w-auto p-1.5 ml-2">
<button name="apply" value="Apply" 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">Apply</button> <button name="apply" value="Apply" 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">
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
<polyline points=" 6,12 10,16 18,8 " stroke="#ffffff"></polyline>
<circle cx="12" cy="12" r="11"></circle>
</g>
</svg>Apply </button>
</div> </div>
<div class="w-full md:w-auto p-1.5 ml-2"> <div class="w-full md:w-auto p-1.5 ml-2">
<button name="cancel" value="Cancel" type="submit" class="flex flex-wrap justify-center w-full px-4 py-2.5 bg-red-500 hover:bg-red-600 font-medium text-sm text-white border border-red-500 rounded-md shadow-button focus:ring-0 focus:outline-none">Cancel</button> <button name="cancel" value="Cancel" type="submit" class="flex flex-wrap justify-center w-full px-4 py-2.5 bg-red-500 hover:bg-red-600 font-medium text-sm text-white border border-red-500 rounded-md shadow-button focus:ring-0 focus:outline-none">
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
<line x1="16" y1="8" x2="8" y2="16" stroke="#ffffff"></line>
<line x1="16" y1="16" x2="8" y2="8" stroke="#ffffff"></line>
<circle cx="12" cy="12" r="11"></circle>
</g>
</svg>Cancel </button>
</div> </div>
{% else %} {% else %}
<div class="w-full md:w-auto p-1.5"> <div class="w-full md:w-auto p-1.5">
<button name="edit" value="edit" 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">Edit</button> <button name="edit" value="edit" 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">
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
<line x1="2" y1="23" x2="22" y2="23" stroke="#ffffff"></line>
<line data-cap="butt" x1="13" y1="5" x2="17" y2="9"></line>
<polygon points="8 18 3 19 4 14 16 2 20 6 8 18"></polygon>
</g>
</svg>Edit </button>
</div> </div>
{% endif %} {% endif %}
</div> </div>

View File

@@ -1,27 +1,24 @@
{% from 'style.html' import circular_info_messages_svg, green_cross_close_svg, red_cross_close_svg, circular_error_messages_svg %}
{% for m in messages %} {% for m in messages %}
<section class="py-4" id="messages_{{ m[0] }}" role="alert"> <section class="py-4" id="messages_{{ m[0] }}" role="alert">
<div class="container px-4 mx-auto"> <div class="container px-4 mx-auto">
<div class="p-6 text-green-800 rounded-lg bg-green-50 border border-green-500 dark:bg-gray-500 dark:text-green-400 rounded-md"> <div class="p-6 bg-green-100 border border-green-200 rounded-md">
<div class="flex flex-wrap justify-between items-center -m-2"> <div class="flex flex-wrap justify-between items-center -m-2">
<div class="flex-1 p-2"> <div class="flex-1 p-2">
<div class="flex flex-wrap -m-1"> <div class="flex flex-wrap -m-1">
<div class="w-auto p-1"> <div class="w-auto p-1">
{{ circular_info_messages_svg | safe }} <svg class="relative top-0.5" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12.4732 4.80667C12.4112 4.74418 12.3375 4.69458 12.2563 4.66074C12.175 4.62689 12.0879 4.60947 11.9999 4.60947C11.9119 4.60947 11.8247 4.62689 11.7435 4.66074C11.6623 4.69458 11.5885 4.74418 11.5266 4.80667L6.55989 9.78L4.47322 7.68667C4.40887 7.62451 4.33291 7.57563 4.24967 7.54283C4.16644 7.51003 4.07755 7.49394 3.9881 7.49549C3.89865 7.49703 3.81037 7.51619 3.72832 7.55185C3.64627 7.58751 3.57204 7.63898 3.50989 7.70333C3.44773 7.76768 3.39885 7.84364 3.36605 7.92688C3.33324 8.01011 3.31716 8.099 3.31871 8.18845C3.32025 8.2779 3.3394 8.36618 3.37507 8.44823C3.41073 8.53028 3.4622 8.60451 3.52655 8.66667L6.08655 11.2267C6.14853 11.2892 6.22226 11.3387 6.3035 11.3726C6.38474 11.4064 6.47188 11.4239 6.55989 11.4239C6.64789 11.4239 6.73503 11.4064 6.81627 11.3726C6.89751 11.3387 6.97124 11.2892 7.03322 11.2267L12.4732 5.78667C12.5409 5.72424 12.5949 5.64847 12.6318 5.56414C12.6688 5.4798 12.6878 5.38873 12.6878 5.29667C12.6878 5.2046 12.6688 5.11353 12.6318 5.02919C12.5949 4.94486 12.5409 4.86909 12.4732 4.80667Z" fill="#2AD168"></path>
</svg>
</div> </div>
<div class="flex-1 p-1">
<h3 class="infomsg font-medium text-sm text-green-900">{{ m[1] }}</h3></div>
<ul class="ml-4 mt-1">
<li class="font-semibold text-sm text-green-500 error_msg"><span class="bold">INFO:</span></li>
<li class="font-medium text-sm text-green-500 infomsg">{{ m[1] }}</li>
</ul>
</div> </div>
</div> </div>
<div class="w-auto p-2"> <div class="w-auto p-2">
<button type="button" class="ms-auto bg-green-50 text-green-500 rounded-lg focus:ring-0 focus:ring-green-400 p-1.5 hover:bg-green-200 inline-flex items-center justify-center h-8 w-8 focus:outline-none dark:bg-gray-800 dark:text-green-400 dark:hover:bg-gray-700" data-dismiss-target="#messages_{{ m[0] }}" aria-label="Close"><span class="sr-only">Close</span> <button type="button" class="ml-auto bg-green-100 text-green-500 rounded-lg focus:ring-0 focus:ring-green-400 p-1.5 hover:bg-green-200 inline-flex h-8 w-8 focus:outline-none" data-dismiss-target="#messages_{{ m[0] }}" aria-label="Close"><span class="sr-only">Close</span>
{{ green_cross_close_svg | safe }} <svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
</svg>
</button> </button>
</div> </div>
</div> </div>
@@ -32,27 +29,27 @@
{% if err_messages %} {% if err_messages %}
<section class="py-4" id="err_messages_{{ err_messages[0][0] }}" role="alert"> <section class="py-4" id="err_messages_{{ err_messages[0][0] }}" role="alert">
<div class="container px-4 mx-auto"> <div class="container px-4 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="p-6 bg-red-100 border border-red-200 rounded-md">
<div class="flex flex-wrap justify-between items-center -m-2"> <div class="flex flex-wrap justify-between items-center -m-2">
<div class="flex-1 p-2"> <div class="flex-1 p-2">
<div class="flex flex-wrap -m-1"> <div class="flex flex-wrap -m-1">
<div class="w-auto p-1"> <div class="w-auto p-1">
{{ circular_error_messages_svg | safe }}
</div>
{% if err_messages %}
<ul class="ml-4 mt-1">
<li class="font-semibold text-sm text-red-500 error_msg"><span class="bold">ERROR:</span></li>
{% for m in err_messages %} {% for m in err_messages %}
<li class="font-medium text-sm text-red-500 error_msg">{{ m[1] }}</li> <div class="flex-1 p-1">
<h3 class="font-medium text-sm text-red-900 error_msg">
<p class="error_msg">Error: {{ m[1] }}</p>
</h3>
</div>
{% endfor %} {% endfor %}
</ul> </div>
{% endif %}
</div> </div>
</div> </div>
<div class="w-auto p-2"> <div class="w-auto p-2">
<button type="button" class="ml-auto bg-red-100 text-red-500 rounded-lg focus:ring-0 focus:ring-red-400 p-1.5 hover:bg-red-200 inline-flex h-8 w-8 focus:outline-none inline-flex items-center justify-center h-8 w-8 dark:bg-gray-800 dark:text-red-400 dark:hover:bg-gray-700" data-dismiss-target="#err_messages_{{ err_messages[0][0] }}" aria-label="Close"> <button type="button" class="ml-auto bg-red-100 text-red-500 rounded-lg focus:ring-0 focus:ring-red-400 p-1.5 hover:bg-red-200 inline-flex h-8 w-8 focus:outline-none" data-dismiss-target="#err_messages_{{ err_messages[0][0] }}" aria-label="Close">
<span class="sr-only">Close</span> <span class="sr-only">Close</span>
{{ red_cross_close_svg | safe }} <svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
</svg>
</button> </button>
</div> </div>
</div> </div>
@@ -60,3 +57,4 @@
</div> </div>
</section> </section>
{% endif %} {% endif %}
<!-- todo messages colors better for darkmode -->

View File

@@ -1,17 +1,23 @@
{% include 'header.html' %} {% include 'header.html' %}
{% from 'style.html' import index_wallet_svg, index_trading_svg, index_support_svg %}
<div class="container mx-auto"> <div class="container mx-auto">
<section class="relative py-24 overflow-hidden"> <section class="relative py-24 overflow-hidden">
<div class="container px-4 mx-auto mb-16 md:mb-0"> <div class="container px-4 mx-auto mb-16 md:mb-0">
<div class="md:w-1/2 pl-4"> <div class="md:w-1/2 pl-4">
<span class="inline-block py-1 px-3 mb-4 text-xs leading-5 bg-blue-500 text-white font-medium rounded-full shadow-sm">(BSX) BasicSwap v{{ version }} - (GUI) v.3.0.0</span> <span class="inline-block py-1 px-3 mb-4 text-xs leading-5 bg-blue-500 text-white font-medium rounded-full shadow-sm">(BSX) BasicSwap v{{ version }}</span>
<h3 class="mb-6 text-4xl md:text-5xl leading-tight text-coolGray-900 font-bold tracking-tighter dark:text-white">Welcome to BasicSwap DEX</h3> <h3 class="mb-6 text-4xl md:text-5xl leading-tight text-coolGray-900 font-bold tracking-tighter dark:text-white">Welcome to BasicSwap DEX</h3>
<p class="mb-12 text-lg md:text-xl text-coolGray-500 dark:text-gray-300 font-medium">Swap cryptocurrencies in <span class="underline">total privacy</span> with no middlemen, fees, <br> or restrictions. </p> <p class="mb-12 text-lg md:text-xl text-coolGray-500 dark:text-gray-300 font-medium">Swap cryptocurrencies in <span class="underline">total privacy</span> with no middlemen, fees, <br> or restrictions. </p>
<div class="flex flex-wrap mb-10 text-center md:text-left"> <div class="flex flex-wrap mb-10 text-center md:text-left">
<div class="w-full md:w-auto mb-6 md:mb-0 md:pr-6"> <div class="w-full md:w-auto mb-6 md:mb-0 md:pr-6">
<a href="/wallets"> <a href="/wallets">
<div class="inline-flex h-14 w-14 mx-auto items-center justify-center text-white bg-blue-500 rounded-lg"> <div class="inline-flex h-14 w-14 mx-auto items-center justify-center text-white bg-blue-500 rounded-lg">
{{ index_wallet_svg | safe }} <svg width="21" height="21" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
<path d="M6,3H3C1.895,3,1,3.895,1,5 v0c0,1.105,0.895,2,2,2"></path>
<polyline points=" 6,7 6,1 20,1 20,7 " stroke="#ffffff"></polyline>
<path d="M23,7H3 C1.895,7,1,6.105,1,5v15c0,1.657,1.343,3,3,3h19V7z"></path>
<circle cx="17" cy="15" r="2"></circle>
</g>
</svg>
</div> </div>
</div> </div>
<div class="w-full md:flex-1 md:pt-3"> <div class="w-full md:flex-1 md:pt-3">
@@ -26,7 +32,16 @@
<div class="w-full md:w-auto mb-6 md:mb-0 md:pr-6"> <div class="w-full md:w-auto mb-6 md:mb-0 md:pr-6">
<a href="/offers"> <a href="/offers">
<div class="inline-flex h-14 w-14 mx-auto items-center justify-center text-white bg-blue-500 rounded-lg"> <div class="inline-flex h-14 w-14 mx-auto items-center justify-center text-white bg-blue-500 rounded-lg">
{{ index_trading_svg | safe }} <svg width="21" height="21" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
<circle cx="5" cy="5" r="4"></circle>
<circle cx="19" cy="19" r="4"></circle>
<polyline data-cap="butt" points="13,5 21,5 21,11 " stroke="#ffffff"></polyline>
<polyline data-cap="butt" points="11,19 3,19 3,13 " stroke="#ffffff"></polyline>
<polyline points=" 16,2 13,5 16,8 " stroke="#ffffff"></polyline>
<polyline points=" 8,16 11,19 8,22 " stroke="#ffffff"></polyline>
</g>
</svg>
</div> </div>
</div> </div>
<div class="w-full md:flex-1 md:pt-3"> <div class="w-full md:flex-1 md:pt-3">
@@ -41,7 +56,13 @@
<div class="w-full md:w-auto mb-6 md:mb-0 md:pr-6"> <div class="w-full md:w-auto mb-6 md:mb-0 md:pr-6">
<a href="https://academy.particl.io/en/latest/faq/get_support.html" target="_blank"> <a href="https://academy.particl.io/en/latest/faq/get_support.html" target="_blank">
<div class="inline-flex h-14 w-14 mx-auto items-center justify-center text-white bg-blue-500 rounded-lg"> <div class="inline-flex h-14 w-14 mx-auto items-center justify-center text-white bg-blue-500 rounded-lg">
{{ index_support_svg | safe }} <svg width="22" height="22" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
<line x1="23" y1="11" x2="23" y2="16" stroke="#ffffff"></line>
<polygon points="12,13 2,8 12,3 22,8 "></polygon>
<path data-cap="butt" d="M5,9.5V18c0,1.657,3.134,3,7,3 s7-1.343,7-3V9.5"></path>
</g>
</svg>
</div> </div>
</div> </div>
<div class="w-full md:flex-1 md:pt-3"> <div class="w-full md:flex-1 md:pt-3">

View File

@@ -1,6 +1,4 @@
{% include 'header.html' %} {% include 'header.html' %}
{% from 'style.html' import breadcrumb_line_svg, input_arrow_down_svg, circular_arrows_svg, confirm_green_svg, green_cross_close_svg %}
<div class="container mx-auto"> <div class="container mx-auto">
<section class="p-5 mt-5"> <section class="p-5 mt-5">
<div class="flex flex-wrap items-center -m-2"> <div class="flex flex-wrap items-center -m-2">
@@ -12,13 +10,17 @@
</a> </a>
</li> </li>
<li> <li>
{{ breadcrumb_line_svg | safe }} <svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li> </li>
<li> <li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="#">Offer</a> <a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="#">Offer</a>
</li> </li>
<li> <li>
{{ breadcrumb_line_svg | safe }} <svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li> </li>
<li> <li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="{{ offer_id }}">OFFER ID: {{ offer_id }}</a> <a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="{{ offer_id }}">OFFER ID: {{ offer_id }}</a>
@@ -35,17 +37,29 @@
<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=""> <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="">
<div class="relative z-20 flex flex-wrap items-center -m-3"> <div class="relative z-20 flex flex-wrap items-center -m-3">
<div class="w-full md:w-1/2 p-3"> <div class="w-full md:w-1/2 p-3">
<h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">Offer</h2> <h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">Offer (normal)</h2>
<p class="font-normal text-coolGray-200 dark:text-white"><span class="bold">OFFER ID:</span> {{ offer_id }}</p> <p class="font-normal text-coolGray-200 dark:text-white">Offer ID: {{ offer_id }}</p>
</div> </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"> <div class="w-full md:w-1/2 p-3 p-6 container flex flex-wrap items-center justify-end items-center mx-auto">
{% if refresh %} {% if refresh %}
<a id="refresh" href="/offer/{{ offer_id }}" 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"> <a id="refresh" href="/offer/{{ offer_id }}" class="flex flex-wrap justify-center px-5 py-4 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white border dark:text-white dark:hover:text-white dark:bg-gray-600 dark:hover:bg-gray-700 dark:border-gray-600 dark:hover:border-gray-600 rounded-md shadow-button focus:ring-0 focus:outline-none">
{{ circular_arrows_svg | safe }}<span>Refresh {{ refresh }} seconds</span> <svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g fill="#ffffff">
<path fill="#ffffff" d="M12,3c1.989,0,3.873,0.65,5.43,1.833l-3.604,3.393l9.167,0.983L22.562,0l-3.655,3.442 C16.957,1.862,14.545,1,12,1C5.935,1,1,5.935,1,12h2C3,7.037,7.037,3,12,3z"></path>
<path data-color="color-2" d="M12,21c-1.989,0-3.873-0.65-5.43-1.833l3.604-3.393l-9.167-0.983L1.438,24l3.655-3.442 C7.043,22.138,9.455,23,12,23c6.065,0,11-4.935,11-11h-2C21,16.963,16.963,21,12,21z"></path>
</g>
</svg>
<span>Refresh {{ refresh }} seconds</span>
</a> </a>
{% else %} {% else %}
<a id="refresh" href="/offer/{{ offer_id }}" 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"> <a id="refresh" href="/offer/{{ offer_id }}" class="flex flex-wrap justify-center px-5 py-4 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white borderdark:text-white dark:hover:text-white dark:bg-gray-600 dark:hover:bg-gray-700 dark:border-gray-600 dark:hover:border-gray-600 border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none">
{{ circular_arrows_svg | safe }}<span>Refresh</span> <svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g fill="#ffffff">
<path fill="#ffffff" d="M12,3c1.989,0,3.873,0.65,5.43,1.833l-3.604,3.393l9.167,0.983L22.562,0l-3.655,3.442 C16.957,1.862,14.545,1,12,1C5.935,1,1,5.935,1,12h2C3,7.037,7.037,3,12,3z"></path>
<path data-color="color-2" d="M12,21c-1.989,0-3.873-0.65-5.43-1.833l3.604-3.393l-9.167-0.983L1.438,24l3.655-3.442 C7.043,22.138,9.455,23,12,23c6.065,0,11-4.935,11-11h-2C21,16.963,16.963,21,12,21z"></path>
</g>
</svg>
<span>Refresh</span>
</a> </a>
{% endif %} {% endif %}
</div> </div>
@@ -55,30 +69,37 @@
</section> </section>
{% include 'inc_messages.html' %} {% include 'inc_messages.html' %}
{% if sent_bid_id %} {% if sent_bid_id %}
<section class="py-4" id="messages_send_bid_id" role="alert"> <section class="py-4">
<div class="container px-4 mx-auto"> <div class="container px-4 mx-auto">
<div class="p-6 bg-green-100 border border-green-200 rounded-md"> <div class="p-6 bg-green-100 border border-green-200 rounded-md">
<div class="flex flex-wrap justify-between items-center -m-2"> <div class="flex flex-wrap justify-between items-center -m-2">
<div class="flex-1 p-2"> <div class="flex-1 p-2">
<div class="flex flex-wrap -m-1"> <div class="flex flex-wrap -m-1">
<div class="w-auto p-1"> <div class="w-auto p-1">
{{ confirm_green_svg | safe }} <svg class="relative top-0.5" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12.4732 4.80667C12.4112 4.74418 12.3375 4.69458 12.2563 4.66074C12.175 4.62689 12.0879 4.60947 11.9999 4.60947C11.9119 4.60947 11.8247 4.62689 11.7435 4.66074C11.6623 4.69458 11.5885 4.74418 11.5266 4.80667L6.55989 9.78L4.47322 7.68667C4.40887 7.62451 4.33291 7.57563 4.24967 7.54283C4.16644 7.51003 4.07755 7.49394 3.9881 7.49549C3.89865 7.49703 3.81037 7.51619 3.72832 7.55185C3.64627 7.58751 3.57204 7.63898 3.50989 7.70333C3.44773 7.76768 3.39885 7.84364 3.36605 7.92688C3.33324 8.01011 3.31716 8.099 3.31871 8.18845C3.32025 8.2779 3.3394 8.36618 3.37507 8.44823C3.41073 8.53028 3.4622 8.60451 3.52655 8.66667L6.08655 11.2267C6.14853 11.2892 6.22226 11.3387 6.3035 11.3726C6.38474 11.4064 6.47188 11.4239 6.55989 11.4239C6.64789 11.4239 6.73503 11.4064 6.81627 11.3726C6.89751 11.3387 6.97124 11.2892 7.03322 11.2267L12.4732 5.78667C12.5409 5.72424 12.5949 5.64847 12.6318 5.56414C12.6688 5.4798 12.6878 5.38873 12.6878 5.29667C12.6878 5.2046 12.6688 5.11353 12.6318 5.02919C12.5949 4.94486 12.5409 4.86909 12.4732 4.80667Z" fill="#2AD168"></path>
</svg>
</div> </div>
<div class="flex-1 p-1"> <div class="flex-1 p-1">
<h3 class="infomsg font-medium text-sm text-green-900">Sent Bid {{ sent_bid_id }}</h3></div> <h3 class="font-medium text-sm text-green-900">
<a href="/bid/{{ sent_bid_id }}">Sent Bid {{ sent_bid_id }}</a>
</h3>
</div>
</div> </div>
</div> </div>
<div class="w-auto p-2"> <div class="w-auto p-2">
<button type="button" class="ml-auto bg-green-100 text-green-500 rounded-lg focus:ring-0 focus:ring-green-400 p-1.5 hover:bg-green-200 inline-flex h-8 w-8 focus:outline-none" data-dismiss-target="#messages_send_bid_id" aria-label="Close"><span class="sr-only">Close</span> <a href="#">
{{ green_cross_close_svg | safe }} <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
</button> <path d="M8.94004 8L13.14 3.80667C13.2656 3.68113 13.3361 3.51087 13.3361 3.33333C13.3361 3.1558 13.2656 2.98554 13.14 2.86C13.0145 2.73447 12.8442 2.66394 12.6667 2.66394C12.4892 2.66394 12.3189 2.73447 12.1934 2.86L8.00004 7.06L3.80671 2.86C3.68117 2.73447 3.51091 2.66394 3.33337 2.66394C3.15584 2.66394 2.98558 2.73447 2.86004 2.86C2.7345 2.98554 2.66398 3.1558 2.66398 3.33333C2.66398 3.51087 2.7345 3.68113 2.86004 3.80667L7.06004 8L2.86004 12.1933C2.79756 12.2553 2.74796 12.329 2.71411 12.4103C2.68027 12.4915 2.66284 12.5787 2.66284 12.6667C2.66284 12.7547 2.68027 12.8418 2.71411 12.9231C2.74796 13.0043 2.79756 13.078 2.86004 13.14C2.92202 13.2025 2.99575 13.2521 3.07699 13.2859C3.15823 13.3198 3.24537 13.3372 3.33337 13.3372C3.42138 13.3372 3.50852 13.3198 3.58976 13.2859C3.671 13.2521 3.74473 13.2025 3.80671 13.14L8.00004 8.94L12.1934 13.14C12.2554 13.2025 12.3291 13.2521 12.4103 13.2859C12.4916 13.3198 12.5787 13.3372 12.6667 13.3372C12.7547 13.3372 12.8419 13.3198 12.9231 13.2859C13.0043 13.2521 13.0781 13.2025 13.14 13.14C13.2025 13.078 13.2521 13.0043 13.286 12.9231C13.3198 12.8418 13.3372 12.7547 13.3372 12.6667C13.3372 12.5787 13.3198 12.4915 13.286 12.4103C13.2521 12.329 13.2025 12.2553 13.14 12.1933L8.94004 8Z" fill="#156633"></path>
</svg>
</a>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
{% endif %} {% endif %}
<section> <section>
<div class="pl-6 pr-6 pt-0 pb-0 mt-5 h-full overflow-hidden"> <div class="pl-6 pr-6 pt-0 pb-0 mt-5 h-full overflow-hidden">
<div class="pb-6 border-coolGray-100"> <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 -m-2">
@@ -234,7 +255,7 @@
</tr> </tr>
<tr class="opacity-100 text-gray-500 dark:text-gray-100 hover:bg-coolGray-200 dark:hover:bg-gray-600"> <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">Chain A local fee rate</td> <td class="py-3 px-6 bold">Chain A local fee rate</td>
<td class="py-3 px-6">{{ data.a_fee_rate_verify }} (Fee source: {{ data.a_fee_rate_verify_src }}{% if data.a_fee_warn == true %} WARNING {% endif %})</td> <td class="py-3 px-6">{{ data.a_fee_rate_verify }} (Fee source: {{ data.a_fee_rate_verify_src }}{% if data.a_fee_warn == true %} WARNING{% endif %})</td>
</tr> </tr>
{% endif %} {% endif %}
</table> </table>
@@ -339,7 +360,9 @@
<td class="pr-3 px-6 bold">Auto Accept Strategy:</td> <td class="pr-3 px-6 bold">Auto Accept Strategy:</td>
<td class="py-3 px-6"> <td class="py-3 px-6">
<div class="relative"> <div class="relative">
{{ input_arrow_down_svg | safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<select name="automation_strat_id" class="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"> <select name="automation_strat_id" class="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">
<option value="-1" {% if data.automation_strat_id==-1 %} selected{% endif %}>None</option> <option value="-1" {% if data.automation_strat_id==-1 %} selected{% endif %}>None</option>
{% for a in data.automation_strategies %} {% for a in data.automation_strategies %}
@@ -397,10 +420,8 @@
</thead> </thead>
<tr class="opacity-100 text-gray-500 dark:text-gray-100 hover:bg-coolGray-200 dark:hover:bg-gray-600 h-20"> <tr class="opacity-100 text-gray-500 dark:text-gray-100 hover:bg-coolGray-200 dark:hover:bg-gray-600 h-20">
<td class="py-3 px-6">Amount you will get <span class="bold" id="bid_amt_from">{{ data.amt_from }}</span> {{ data.tla_from }} <td class="py-3 px-6">Amount you will get <span class="bold" id="bid_amt_from">{{ data.amt_from }}</span> {{ data.tla_from }}
{% if data.xmr_type == true %} {% if data.xmr_type == true %} (excluding estimated {{ data.amt_from_lock_spend_tx_fee }} {{ data.tla_from }} in tx fees).
(excluding estimated {{ data.amt_from_lock_spend_tx_fee }} {{ data.tla_from }} in tx fees). {% else %} (excluding a tx fee).
{% else %}
(excluding a tx fee).
{% endif %}</td> {% endif %}</td>
<td class="py-3 px-6">Amount you will send <span class="bold" id="bid_amt_to">{{ data.amt_to }}</span> {{ data.tla_to }} <td class="py-3 px-6">Amount you will send <span class="bold" id="bid_amt_to">{{ data.amt_to }}</span> {{ data.tla_to }}
</td> </td>
@@ -410,7 +431,9 @@
<td class="py-3 px-6"> <td class="py-3 px-6">
<div class="w-full md:flex-1"> <div class="w-full md:flex-1">
<div class="relative"> <div class="relative">
{{ input_arrow_down_svg | safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<select class="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" name="addr_from"> <select class="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" name="addr_from">
{% for a in addrs %} {% for a in addrs %}
<option value="{{ a[0] }}" {% if data.nb_addr_from==a[0] %} selected{% endif %}>{{ a[0] }} {{ a[1] }}</option> <option value="{{ a[0] }}" {% if data.nb_addr_from==a[0] %} selected{% endif %}>{{ a[0] }} {{ a[1] }}</option>
@@ -448,7 +471,9 @@
<td class="py-3 px-6"> <td class="py-3 px-6">
<div class="w-full md:flex-1"> <div class="w-full md:flex-1">
<div class="relative"> <div class="relative">
{{ input_arrow_down_svg | safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<select class="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" name="debugind"> <select class="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" name="debugind">
<option{% if data.debug_ind=="-1" %} selected{% endif %} value="-1">None</option> <option{% if data.debug_ind=="-1" %} selected{% endif %} value="-1">None</option>
{% for a in data.debug_options %} {% for a in data.debug_options %}

View File

@@ -1,20 +1,43 @@
{% include 'header.html' %} {% from 'style.html' import breadcrumb_line_svg, input_down_arrow_offer_svg, select_network_svg, select_address_svg, select_swap_type_svg, select_bid_amount_svg, select_rate_svg, step_one_svg, step_two_svg, step_three_svg, select_setup_svg, input_time_svg, select_target_svg , select_auto_strategy_svg %} {% include 'header.html' %}
<script src="static/js/coin_icons.js"></script>
<div class="container mx-auto"> <div class="container mx-auto">
<section class="p-5 mt-5"> <section class="p-5 mt-5">
<div class="flex flex-wrap items-center -m-2"> <div class="flex flex-wrap items-center -m-2">
<div class="w-full md:w-1/2 p-2"> <div class="w-full md:w-1/2 p-2">
<ul class="flex flex-wrap items-center gap-x-3 mb-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="/"> <li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/">
<p>Home</p> <p>Home</p>
</a> </li> </a>
<li>{{ breadcrumb_line_svg | safe }}</li> </li>
<li><a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/newoffer">Place</a></li> <li>
<li>{{ breadcrumb_line_svg | safe }}</li> <svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<li><a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="#">Setup</a></li> <path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
<li>{{ breadcrumb_line_svg | safe }}</li> </svg>
<li><a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="#">Confirm</a></li> </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="/newoffer">Place an new offer</a>
</li>
<li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
<li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="#">Setup offers parameters</a>
</li>
<li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
<li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="#">Confirm your offer information</a>
</li>
<li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
</ul> </ul>
</div> </div>
</div> </div>
@@ -27,8 +50,8 @@
<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=""> <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="">
<div class="relative z-20 flex flex-wrap items-center -m-3"> <div class="relative z-20 flex flex-wrap items-center -m-3">
<div class="w-full md:w-1/2 p-3"> <div class="w-full md:w-1/2 p-3">
<h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">Confirm your Offer</h2> <h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">Confirm your offer information</h2>
<p class="font-normal text-coolGray-200 dark:text-white">Place an order on the network order book.</p> <p class="font-normal text-coolGray-200 dark:text-white">Place an order on the order book.</p>
</div> </div>
</div> </div>
</div> </div>
@@ -36,26 +59,38 @@
</section> </section>
{% include 'inc_messages.html' %} {% include 'inc_messages.html' %}
<section> <section>
<div class="p-5 mb-5"> <div class="p-5 mb-10">
<div class="mx-4 p-4"> <div class="mx-4 p-4">
<div class="flex items-center"> <div class="flex items-center">
<div class="flex items-center text-teal-600 relative"> <div class="flex items-center text-teal-600 relative">
<div class="rounded-full h-12 w-12 py-3 border-2 border-blue-500"> <div class="rounded-full h-12 w-12 py-3 border-2 border-blue-500">
{{ step_one_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 24 24">
<g fill="#3b82f6">
<polygon points="14.5 23.5 11.5 23.5 11.5 4.321 6.766 8.108 4.892 5.766 11.474 0.5 14.5 0.5 14.5 23.5" fill="#3b82f6"></polygon>
</g>
</svg>
</div> </div>
<div class="absolute top-0 -ml-10 text-center mt-16 w-32 text-xs font-medium uppercase dark:text-white text-gray-600">Step 1</div> <div class="absolute top-0 -ml-10 text-center mt-16 w-32 text-xs font-medium uppercase dark:text-white text-gray-600">Step 1</div>
</div> </div>
<div class="flex-auto border-t-2 border-blue-500 dark:border-blue-500"></div> <div class="flex-auto border-t-2 border-blue-500 dark:border-blue-500"></div>
<div class="flex items-center text-teal-600 relative "> <div class="flex items-center text-teal-600 relative ">
<div class="rounded-full transition duration-500 ease-in-out h-12 w-12 py-3 border-2 border-blue-500 dark:border-blue-500"> <div class="rounded-full transition duration-500 ease-in-out h-12 w-12 py-3 border-2 border-blue-500 dark:border-blue-500">
{{ step_two_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 24 24">
<g fill="#3b82f6">
<path d="M19.5,23.5H4.5V20.2l.667-.445C9.549,16.828,16.5,10.78,16.5,7c0-2.654-1.682-4-5-4A9.108,9.108,0,0,0,7.333,4.248L6.084,5.08,4.42,2.584l1.247-.832A11.963,11.963,0,0,1,11.5,0c4.935,0,8,2.683,8,7,0,5-6.5,10.662-10.232,13.5H19.5ZM6,21H6Z" fill="#3b82f6"></path>
</g>
</svg>
</div> </div>
<div class="absolute top-0 -ml-10 text-center mt-16 w-32 text-xs font-medium uppercase dark:text-white text-gray-600">Step 2</div> <div class="absolute top-0 -ml-10 text-center mt-16 w-32 text-xs font-medium uppercase dark:text-white text-gray-600">Step 2</div>
</div> </div>
<div class="flex-auto border-t-2 border-blue-500 dark:border-blue-500"></div> <div class="flex-auto border-t-2 border-blue-500 dark:border-blue-500"></div>
<div class="flex items-center text-gray-500 relative"> <div class="flex items-center text-gray-500 relative">
<div class="rounded-full transition duration-500 ease-in-out h-12 w-12 py-3 border-2 border-blue-500 dark:border-blue-500"> <div class="rounded-full transition duration-500 ease-in-out h-12 w-12 py-3 border-2 border-blue-500 dark:border-blue-500">
{{ step_three_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 24 24">
<g fill="#3b82f6">
<polygon points="9 21 1 13 4 10 9 15 21 3 24 6 9 21" fill="#3b82f6"></polygon>
</g>
</svg>
</div> </div>
<div class="absolute top-0 -ml-10 text-center mt-16 w-32 text-xs font-medium uppercase dark:text-white text-gray-600">Confirm</div> <div class="absolute top-0 -ml-10 text-center mt-16 w-32 text-xs font-medium uppercase dark:text-white text-gray-600">Confirm</div>
</div> </div>
@@ -66,19 +101,34 @@
<section class="py-3"> <section class="py-3">
<div class="container px-4 mx-auto"> <div class="container px-4 mx-auto">
<div class="p-8 bg-coolGray-100 dark:bg-gray-500 rounded-xl"> <div class="p-8 bg-coolGray-100 dark:bg-gray-500 rounded-xl">
<div class="flex flex-wrap items-center justify-between -mx-4 pb-6 border-gray-400 border-opacity-20"> </div> <div class="flex flex-wrap items-center justify-between -mx-4 mb-8 pb-6 border-b border-gray-400 border-opacity-20">
<div class="w-full sm:w-auto px-4 mb-6 sm:mb-0">
<h4 class="text-2xl font-bold tracking-wide dark:text-white mb-1">CONFIRM</h4>
<!-- todo add subtitle <p class="text-sm text-coolGray-500">Lorem ipsum dolor sit amet</p> -->
</div>
</div>
<form method="post" autocomplete="off" id='form'> <form method="post" autocomplete="off" id='form'>
<div class="py-3 border-b items-center justify-between -mx-4 mb-6 pb-3 border-gray-400 border-opacity-20"> <div class="py-3 border-b items-center justify-between -mx-4 mb-6 pb-6 border-gray-400 border-opacity-20">
<div class="w-full md:w-10/12"> <div class="w-full md:w-10/12">
<div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0"> <div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0">
<div class="w-full md:w-1/3 p-6"> <div class="w-full md:w-1/3 p-3">
<p class="text-sm text-coolGray-800 dark:text-white font-semibold">Select Network</p> <p class="text-sm text-coolGray-800 dark:text-white font-semibold">Select Network</p>
</div> </div>
<div class="w-full md:flex-1 p-3"> <div class="w-full md:flex-1 p-3">
<div class="relative"> <div class="relative">
{{ input_down_arrow_offer_svg | safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_network_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<line data-cap="butt" x1="7.6" y1="10.5" x2="16.4" y2="5.5" stroke="#3b82f6"></line>
<line data-cap="butt" x1="7.6" y1="13.5" x2="16.4" y2="18.5" stroke="#3b82f6"></line>
<circle cx="5" cy="12" r="3"></circle>
<circle cx="19" cy="4" r="3"></circle>
<circle cx="19" cy="20" r="3"></circle>
</g>
</svg>
</div> </div>
<select class="cursor-not-allowed disabled-select pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-" name="addr_to" disabled> <select class="cursor-not-allowed disabled-select pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-" name="addr_to" disabled>
<option{% if data.addr_to=="-1" %} selected{% endif %} value="-1">Public Network</option> <option{% if data.addr_to=="-1" %} selected{% endif %} value="-1">Public Network</option>
@@ -91,19 +141,28 @@
</div> </div>
</div> </div>
</div> </div>
<div class="py-0 border-b items-center justify-between -mx-4 mb-6 pb-3 border-gray-400 border-opacity-20"> <div class="py-3 border-b items-center justify-between -mx-4 mb-6 pb-6 border-gray-400 border-opacity-20">
<div class="w-full md:w-10/12"> <div class="w-full md:w-10/12">
<div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0"> <div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0">
<div class="w-full md:w-1/3 p-6"> <div class="w-full md:w-1/3 p-3">
<p class="text-sm text-coolGray-800 dark:text-white font-semibold">Select Address</p> <p class="text-sm text-coolGray-800 dark:text-white font-semibold">Select Address</p>
</div> </div>
<div class="w-full md:flex-1 p-3"> <div class="w-full md:flex-1 p-3">
<div class="relative"> <div class="relative">
{{ input_down_arrow_offer_svg | safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_address_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path data-cap="butt" d="M11.992,11.737,14.2,13.4A2,2,0,0,1,15,15v1H7V15a2,2,0,0,1,.8-1.6l2.208-1.663" stroke="#3b82f6"></path>
<rect x="9" y="7" width="4" height="5" rx="2" ry="2" stroke="#3b82f6"></rect>
<path d="M2,1H18a2,2,0,0,1,2,2V21a2,2,0,0,1-2,2H2Z"></path>
<line x1="23" y1="5" x2="23" y2="9" stroke="#3b82f6"></line>
</g>
</svg>
</div> </div>
<select class="cursor-not-allowed disabled-select hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="addr_from" disabled> <select class="cursor-not-allowed disabled-select pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="addr_from" disabled>
{% for a in addrs %} {% for a in addrs %}
<option{% if data.addr_from==a[0] %} selected{% endif %} value="{{ a[0] }}">{{ a[0] }} {{ a[1] }}</option> <option{% if data.addr_from==a[0] %} selected{% endif %} value="{{ a[0] }}">{{ a[0] }} {{ a[1] }}</option>
{% endfor %} {% endfor %}
@@ -114,17 +173,26 @@
</div> </div>
</div> </div>
</div> </div>
<div class="py-0 border-b items-center justify-between -mx-4 mb-6 pb-3 border-gray-400 border-opacity-20"> <div class="py-3 border-b items-center justify-between -mx-4 mb-6 pb-6 border-gray-400 border-opacity-20">
<div class="w-full md:w-10/12"> <div class="w-full md:w-10/12">
<div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0"> <div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0">
<div class="w-full md:w-1/3 p-6"> <div class="w-full md:w-1/3 p-3">
<p class="text-sm text-coolGray-800 dark:text-white font-semibold">Swap Type</p> <p class="text-sm text-coolGray-800 dark:text-white font-semibold">Swap Type</p>
</div> </div>
<div class="w-full md:flex-1 p-3"> <div class="w-full md:flex-1 p-3">
<div class="relative"> <div class="relative">
{{ input_down_arrow_offer_svg | safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_swap_type_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path data-cap="butt" d="M11.992,11.737,14.2,13.4A2,2,0,0,1,15,15v1H7V15a2,2,0,0,1,.8-1.6l2.208-1.663" stroke="#3b82f6"></path>
<rect x="9" y="7" width="4" height="5" rx="2" ry="2" stroke="#3b82f6"></rect>
<path d="M2,1H18a2,2,0,0,1,2,2V21a2,2,0,0,1-2,2H2Z"></path>
<line x1="23" y1="5" x2="23" y2="9" stroke="#3b82f6"></line>
</g>
</svg>
</div> </div>
<select class="cursor-not-allowed disabled-select pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="swap_type" id="swap_type" disabled> <select class="cursor-not-allowed disabled-select pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="swap_type" id="swap_type" disabled>
{% for a in swap_types %} {% for a in swap_types %}
@@ -136,35 +204,47 @@
</div> </div>
</div> </div>
</div> </div>
<div class="py-0 border-b items-center justify-between -mx-4 mb-6 pb-3 border-gray-400 border-opacity-20"> <div class="py-3 border-b items-center justify-between -mx-4 mb-6 pb-6 border-gray-400 border-opacity-20">
<div class="w-full md:w-10/12"> <div class="w-full md:w-10/12">
<div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0"> <div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0">
<div class="w-full md:w-1/3 p-6"> <div class="w-full md:w-1/3 p-3">
<p class="text-sm text-coolGray-800 dark:text-white font-semibold">You Send</p> <p class="text-sm text-coolGray-800 dark:text-white font-semibold">You Send</p>
</div> </div>
<div class="w-full md:flex-1 p-3"> <div class="w-full md:flex-1 p-3">
<div class="flex flex-wrap -m-3"> <div class="flex flex-wrap -m-3">
<div class="w-full md:w-1/2 p-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">Coin You Send:</p>
<div class="custom-select"> <div class="custom-select">
<div class="relative"> <div class="relative">
{{ input_down_arrow_offer_svg | safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<select class="select cursor-not-allowed disabled-select hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-5 focus:ring-0" id="coin_from" name="coin_from" disabled> <path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<select class="select cursor-not-allowed disabled-select hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" id="coin_from" name="coin_from" onchange="set_rate('coin_from');" disabled>
<option value="-1">Select coin you send</option> <option value="-1">Select coin you send</option>
{% for c in coins_from %} {% for c in coins_from %}
<option{% if data.coin_from==c[0] %} selected{% endif %} value="{{ c[0] }}" data-image="/static/images/coins/{{ c[1]|replace(" ", "-") }}-20.png">{{ c[1] }} <option{% if data.coin_from==c[0] %} selected{% endif %} value="{{ c[0] }}" data-image="/static/images/coins/{{ c[1]|replace(" ", "-") }}-20.png">{{ c[1] }}</option>
</option>
{% endfor %} {% endfor %}
</select> </select>
<div class="select-dropdown"> <div class="select-dropdown">
<img class="select-icon" src="" alt=""> <img class="select-image" src="" alt=""> </div> <img class="select-icon" src="" alt="">
<img class="select-image" src="" alt="">
</div>
</div> </div>
</div> </div>
</div> </div>
<div class="w-full md:w-1/2 p-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">Amount You Send</p>
<div class="relative"> <div class="relative">
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> </div> <input class="cursor-not-allowed disabled-input hover:border-blue-500 pr-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-5 focus:ring-0" type="text" id="amt_from" name="amt_from" value="{{ data.amt_from }}" readonly> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path d="M15.6,13.873a2.273,2.273,0,0,1-.825,1.833,4.1,4.1,0,0,1-2.31.829v1.47h-.982V16.563a7.95,7.95,0,0,1-3.07-.617V14.053a8.328,8.328,0,0,0,1.5.545,8.019,8.019,0,0,0,1.568.28V12.654L11,12.468a5.357,5.357,0,0,1-2.012-1.216A2.332,2.332,0,0,1,8.4,9.627a2.123,2.123,0,0,1,.814-1.71,4.143,4.143,0,0,1,2.27-.812v-1.1h.982V7.074a8.126,8.126,0,0,1,2.97.66l-.674,1.678a7.768,7.768,0,0,0-2.3-.559v2.116a11.073,11.073,0,0,1,1.991.932,2.733,2.733,0,0,1,.867.868A2.146,2.146,0,0,1,15.6,13.873ZM10.558,9.627a.678.678,0,0,0,.219.52,2.569,2.569,0,0,0,.707.42V8.881Q10.559,9.017,10.558,9.627Zm2.884,4.354a.646.646,0,0,0-.244-.509,3.173,3.173,0,0,0-.732-.431v1.786Q13.441,14.662,13.442,13.981Z" stroke="none" fill="#3b82f6"></path>
<polyline points="5.346 7.929 6.932 2.237 1.135 2.966"></polyline>
<path data-cap="butt" d="M11.789,23A11,11,0,0,1,6.932,2.237"></path>
<polyline points="18.654 16.071 17.068 21.763 22.865 21.034"></polyline>
<path data-cap="butt" d="M12.211,1a11,11,0,0,1,4.857,20.763"></path>
</g>
</svg>
</div>
<input class="cursor-not-allowed disabled-input pl-10 hover:border-blue-500 pl-10 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-white 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="amt_from" name="amt_from" value="{{ data.amt_from }}" onchange="set_rate('amt_from');" readonly>
</div> </div>
</div> </div>
{% if data.swap_style == 'xmr' %} {% if data.swap_style == 'xmr' %}
@@ -172,7 +252,15 @@
<p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Fee From Confirm Target</p> <p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Fee From Confirm Target</p>
<div class="relative"> <div class="relative">
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_target_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path d="M15.6,13.873a2.273,2.273,0,0,1-.825,1.833,4.1,4.1,0,0,1-2.31.829v1.47h-.982V16.563a7.95,7.95,0,0,1-3.07-.617V14.053a8.328,8.328,0,0,0,1.5.545,8.019,8.019,0,0,0,1.568.28V12.654L11,12.468a5.357,5.357,0,0,1-2.012-1.216A2.332,2.332,0,0,1,8.4,9.627a2.123,2.123,0,0,1,.814-1.71,4.143,4.143,0,0,1,2.27-.812v-1.1h.982V7.074a8.126,8.126,0,0,1,2.97.66l-.674,1.678a7.768,7.768,0,0,0-2.3-.559v2.116a11.073,11.073,0,0,1,1.991.932,2.733,2.733,0,0,1,.867.868A2.146,2.146,0,0,1,15.6,13.873ZM10.558,9.627a.678.678,0,0,0,.219.52,2.569,2.569,0,0,0,.707.42V8.881Q10.559,9.017,10.558,9.627Zm2.884,4.354a.646.646,0,0,0-.244-.509,3.173,3.173,0,0,0-.732-.431v1.786Q13.441,14.662,13.442,13.981Z" stroke="none" fill="#3b82f6"></path>
<polyline points="5.346 7.929 6.932 2.237 1.135 2.966"></polyline>
<path data-cap="butt" d="M11.789,23A11,11,0,0,1,6.932,2.237"></path>
<polyline points="18.654 16.071 17.068 21.763 22.865 21.034"></polyline>
<path data-cap="butt" d="M12.211,1a11,11,0,0,1,4.857,20.763"></path>
</g>
</svg>
</div> </div>
<input class="cursor-not-allowed disabled-input pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" type="number" name="fee_from_conf" min="1" max="32" value="{{ data.fee_from_conf }}" readonly> <input class="cursor-not-allowed disabled-input pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" type="number" name="fee_from_conf" min="1" max="32" value="{{ data.fee_from_conf }}" readonly>
</div> </div>
@@ -181,25 +269,49 @@
<p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Fee Rate From</p> <p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Fee Rate From</p>
<div class="relative"> <div class="relative">
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_rate_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
</div> <input class="cursor-not-allowed disabled-input pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="fee_rate_from" value="{{ data.from_fee_override }}" readonly> <g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
</div> <span class="text-sm mt-2 block dark:text-white"> <b>Fee Rate Source:</b> {{ data.from_fee_src }} </span> <path d="M15.6,13.873a2.273,2.273,0,0,1-.825,1.833,4.1,4.1,0,0,1-2.31.829v1.47h-.982V16.563a7.95,7.95,0,0,1-3.07-.617V14.053a8.328,8.328,0,0,0,1.5.545,8.019,8.019,0,0,0,1.568.28V12.654L11,12.468a5.357,5.357,0,0,1-2.012-1.216A2.332,2.332,0,0,1,8.4,9.627a2.123,2.123,0,0,1,.814-1.71,4.143,4.143,0,0,1,2.27-.812v-1.1h.982V7.074a8.126,8.126,0,0,1,2.97.66l-.674,1.678a7.768,7.768,0,0,0-2.3-.559v2.116a11.073,11.073,0,0,1,1.991.932,2.733,2.733,0,0,1,.867.868A2.146,2.146,0,0,1,15.6,13.873ZM10.558,9.627a.678.678,0,0,0,.219.52,2.569,2.569,0,0,0,.707.42V8.881Q10.559,9.017,10.558,9.627Zm2.884,4.354a.646.646,0,0,0-.244-.509,3.173,3.173,0,0,0-.732-.431v1.786Q13.441,14.662,13.442,13.981Z" stroke="none" fill="#3b82f6"></path>
<polyline points="5.346 7.929 6.932 2.237 1.135 2.966"></polyline>
<path data-cap="butt" d="M11.789,23A11,11,0,0,1,6.932,2.237"></path>
<polyline points="18.654 16.071 17.068 21.763 22.865 21.034"></polyline>
<path data-cap="butt" d="M12.211,1a11,11,0,0,1,4.857,20.763"></path>
</g>
</svg>
</div>
<input class="cursor-not-allowed disabled-input pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="fee_rate_from" value="{{ data.from_fee_override }}" readonly>
</div>
<span class="text-sm mt-2 block dark:text-white">
<b>Fee Rate Source:</b> {{ data.from_fee_src }}
</span>
</div> </div>
<div class="w-full md:w-1/2 p-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">Fee From Increase By</p> <p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Fee From Increase By</p>
<div class="relative"> <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> <div class="relative">
<svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path> <path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg> </svg>
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_rate_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path d="M15.6,13.873a2.273,2.273,0,0,1-.825,1.833,4.1,4.1,0,0,1-2.31.829v1.47h-.982V16.563a7.95,7.95,0,0,1-3.07-.617V14.053a8.328,8.328,0,0,0,1.5.545,8.019,8.019,0,0,0,1.568.28V12.654L11,12.468a5.357,5.357,0,0,1-2.012-1.216A2.332,2.332,0,0,1,8.4,9.627a2.123,2.123,0,0,1,.814-1.71,4.143,4.143,0,0,1,2.27-.812v-1.1h.982V7.074a8.126,8.126,0,0,1,2.97.66l-.674,1.678a7.768,7.768,0,0,0-2.3-.559v2.116a11.073,11.073,0,0,1,1.991.932,2.733,2.733,0,0,1,.867.868A2.146,2.146,0,0,1,15.6,13.873ZM10.558,9.627a.678.678,0,0,0,.219.52,2.569,2.569,0,0,0,.707.42V8.881Q10.559,9.017,10.558,9.627Zm2.884,4.354a.646.646,0,0,0-.244-.509,3.173,3.173,0,0,0-.732-.431v1.786Q13.441,14.662,13.442,13.981Z" stroke="none" fill="#3b82f6"></path>
<polyline points="5.346 7.929 6.932 2.237 1.135 2.966"></polyline>
<path data-cap="butt" d="M11.789,23A11,11,0,0,1,6.932,2.237"></path>
<polyline points="18.654 16.071 17.068 21.763 22.865 21.034"></polyline>
<path data-cap="butt" d="M12.211,1a11,11,0,0,1,4.857,20.763"></path>
</g>
</svg>
</div> </div>
<select class="cursor-not-allowed disabled-select pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="fee_from_extra" disabled> <select class="cursor-not-allowed disabled-select pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="fee_from_extra_" disabled>
<option value="0">None</option> <option value="0">None</option>
<option value="10" {% if data.fee_from_extra==10 %} selected{% endif %}>10%</option> <option value="10" {% if data.fee_from_extra==10 %} selected{% endif %}>10%</option>
<option value="50" {% if data.fee_from_extra==50 %} selected{% endif %}>50%</option> <option value="50" {% if data.fee_from_extra==50 %} selected{% endif %}>50%</option>
<option value="100" {% if data.fee_from_extra==100 %} selected{% endif %}>100%</option> <option value="100" {% if data.fee_from_extra==100 %} selected{% endif %}>100%</option>
</select> </select>
</div> <span class="text-sm mt-2 block dark:text-white"> <b>Lock Tx Spend Fee:</b> {{ data.amt_from_lock_spend_tx_fee }} {{ data.tla_from }} </span> </div>
<span class="text-sm mt-2 block dark:text-white">
<b>Lock Tx Spend Fee:</b> {{ data.amt_from_lock_spend_tx_fee }} {{ data.tla_from }}
</span>
</div> </div>
{% endif %} {% endif %}
</div> </div>
@@ -207,43 +319,63 @@
</div> </div>
</div> </div>
</div> </div>
<div class="py-0 border-b items-center justify-between -mx-4 mb-6 pb-3 border-gray-400 border-opacity-20"> <div class="py-3 border-b items-center justify-between -mx-4 mb-6 pb-6 border-gray-400 border-opacity-20">
<div class="w-full md:w-10/12"> <div class="w-full md:w-10/12">
<div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0"> <div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0">
<div class="w-full md:w-1/3 p-6"> <div class="w-full md:w-1/3 p-3">
<p class="text-sm text-coolGray-800 dark:text-white font-semibold">You Get</p> <p class="text-sm text-coolGray-800 dark:text-white font-semibold">You Get</p>
</div> </div>
<div class="w-full md:flex-1 p-3"> <div class="w-full md:flex-1 p-3">
<div class="flex flex-wrap -m-3"> <div class="flex flex-wrap -m-3">
<div class="w-full md:w-1/2 p-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">Coin You Get</p>
<div class="custom-select"> <div class="custom-select">
<div class="relative"> <div class="relative">
{{ input_down_arrow_offer_svg | safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<select class="cursor-not-allowed disabled-select select hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-5 focus:ring-0" id="coin_to" name="coin_to" disabled> <path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<select class="cursor-not-allowed disabled-select select hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" id="coin_to" name="coin_to" onchange="set_rate('coin_to');" disabled>
<option value="-1"></option> <option value="-1"></option>
{% for c in coins %} {% for c in coins %}
<option{% if data.coin_to==c[0] %} selected{% endif %} value="{{ c[0] }}" data-image="/static/images/coins/{{ c[1]|replace(" ", "-") }}-20.png">{{ c[1] }}</option> <option{% if data.coin_to==c[0] %} selected{% endif %} value="{{ c[0] }}" data-image="/static/images/coins/{{ c[1]|replace(" ", "-") }}-20.png">{{ c[1] }}</option>
{% endfor %} {% endfor %}
</select> </select>
<div class="select-dropdown"> <img class="select-icon" src="" alt=""> <div class="select-dropdown">
<img class="select-icon" src="" alt="">
<img class="select-image" src="" alt=""> <img class="select-image" src="" alt="">
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="w-full md:w-1/2 p-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">Amount You Get</p>
<div class="relative"> <div class="relative">
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> </div> <input class="cursor-not-allowed disabled-input hover:border-blue-500 pr-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-5 focus:ring-0" type="text" id="amt_to" name="amt_to" value="{{ data.amt_to }}" readonly> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path d="M15.6,13.873a2.273,2.273,0,0,1-.825,1.833,4.1,4.1,0,0,1-2.31.829v1.47h-.982V16.563a7.95,7.95,0,0,1-3.07-.617V14.053a8.328,8.328,0,0,0,1.5.545,8.019,8.019,0,0,0,1.568.28V12.654L11,12.468a5.357,5.357,0,0,1-2.012-1.216A2.332,2.332,0,0,1,8.4,9.627a2.123,2.123,0,0,1,.814-1.71,4.143,4.143,0,0,1,2.27-.812v-1.1h.982V7.074a8.126,8.126,0,0,1,2.97.66l-.674,1.678a7.768,7.768,0,0,0-2.3-.559v2.116a11.073,11.073,0,0,1,1.991.932,2.733,2.733,0,0,1,.867.868A2.146,2.146,0,0,1,15.6,13.873ZM10.558,9.627a.678.678,0,0,0,.219.52,2.569,2.569,0,0,0,.707.42V8.881Q10.559,9.017,10.558,9.627Zm2.884,4.354a.646.646,0,0,0-.244-.509,3.173,3.173,0,0,0-.732-.431v1.786Q13.441,14.662,13.442,13.981Z" stroke="none" fill="#3b82f6"></path>
<polyline points="5.346 7.929 6.932 2.237 1.135 2.966"></polyline>
<path data-cap="butt" d="M11.789,23A11,11,0,0,1,6.932,2.237"></path>
<polyline points="18.654 16.071 17.068 21.763 22.865 21.034"></polyline>
<path data-cap="butt" d="M12.211,1a11,11,0,0,1,4.857,20.763"></path>
</g>
</svg>
</div>
<input class="cursor-not-allowed disabled-input pl-10 hover:border-blue-500 pl-10 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-white 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="amt_to" name="amt_to" value="{{ data.amt_to }}" onchange="set_rate('amt_to');" readonly>
</div> </div>
</div> </div>
{% if data.swap_style == 'xmr' and coin_to != '6' %} {% if data.swap_style == 'xmr' %}
<div class="w-full md:w-1/2 p-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">Fee To Confirm Target</p> <p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Fee To Confirm Target</p>
<div class="relative"> <div class="relative">
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_target_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path d="M15.6,13.873a2.273,2.273,0,0,1-.825,1.833,4.1,4.1,0,0,1-2.31.829v1.47h-.982V16.563a7.95,7.95,0,0,1-3.07-.617V14.053a8.328,8.328,0,0,0,1.5.545,8.019,8.019,0,0,0,1.568.28V12.654L11,12.468a5.357,5.357,0,0,1-2.012-1.216A2.332,2.332,0,0,1,8.4,9.627a2.123,2.123,0,0,1,.814-1.71,4.143,4.143,0,0,1,2.27-.812v-1.1h.982V7.074a8.126,8.126,0,0,1,2.97.66l-.674,1.678a7.768,7.768,0,0,0-2.3-.559v2.116a11.073,11.073,0,0,1,1.991.932,2.733,2.733,0,0,1,.867.868A2.146,2.146,0,0,1,15.6,13.873ZM10.558,9.627a.678.678,0,0,0,.219.52,2.569,2.569,0,0,0,.707.42V8.881Q10.559,9.017,10.558,9.627Zm2.884,4.354a.646.646,0,0,0-.244-.509,3.173,3.173,0,0,0-.732-.431v1.786Q13.441,14.662,13.442,13.981Z" stroke="none" fill="#3b82f6"></path>
<polyline points="5.346 7.929 6.932 2.237 1.135 2.966"></polyline>
<path data-cap="butt" d="M11.789,23A11,11,0,0,1,6.932,2.237"></path>
<polyline points="18.654 16.071 17.068 21.763 22.865 21.034"></polyline>
<path data-cap="butt" d="M12.211,1a11,11,0,0,1,4.857,20.763"></path>
</g>
</svg>
</div> </div>
<input class="cursor-not-allowed disabled-input pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" type="number" name="fee_to_conf" min="1" max="32" value="{{ data.fee_to_conf }}" readonly> <input class="cursor-not-allowed disabled-input pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" type="number" name="fee_to_conf" min="1" max="32" value="{{ data.fee_to_conf }}" readonly>
</div> </div>
@@ -252,23 +384,88 @@
<p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Fee Rate To</p> <p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Fee Rate To</p>
<div class="relative"> <div class="relative">
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_rate_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path d="M15.6,13.873a2.273,2.273,0,0,1-.825,1.833,4.1,4.1,0,0,1-2.31.829v1.47h-.982V16.563a7.95,7.95,0,0,1-3.07-.617V14.053a8.328,8.328,0,0,0,1.5.545,8.019,8.019,0,0,0,1.568.28V12.654L11,12.468a5.357,5.357,0,0,1-2.012-1.216A2.332,2.332,0,0,1,8.4,9.627a2.123,2.123,0,0,1,.814-1.71,4.143,4.143,0,0,1,2.27-.812v-1.1h.982V7.074a8.126,8.126,0,0,1,2.97.66l-.674,1.678a7.768,7.768,0,0,0-2.3-.559v2.116a11.073,11.073,0,0,1,1.991.932,2.733,2.733,0,0,1,.867.868A2.146,2.146,0,0,1,15.6,13.873ZM10.558,9.627a.678.678,0,0,0,.219.52,2.569,2.569,0,0,0,.707.42V8.881Q10.559,9.017,10.558,9.627Zm2.884,4.354a.646.646,0,0,0-.244-.509,3.173,3.173,0,0,0-.732-.431v1.786Q13.441,14.662,13.442,13.981Z" stroke="none" fill="#3b82f6"></path>
<polyline points="5.346 7.929 6.932 2.237 1.135 2.966"></polyline>
<path data-cap="butt" d="M11.789,23A11,11,0,0,1,6.932,2.237"></path>
<polyline points="18.654 16.071 17.068 21.763 22.865 21.034"></polyline>
<path data-cap="butt" d="M12.211,1a11,11,0,0,1,4.857,20.763"></path>
</g>
</svg>
</div> </div>
<input class="cursor-not-allowed disabled-input pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="fee_rate_to" value="{{ data.to_fee_override }}" readonly> <input class="cursor-not-allowed disabled-input pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="fee_rate_to" value="{{ data.to_fee_override }}" readonly>
</div> <span class="text-sm mt-2 block dark:text-white"> <b>Fee Rate Source:</b> {{ data.to_fee_src }} </span> </div>
<span class="text-sm mt-2 block dark:text-white">
<b>Fee Rate Source:</b> {{ data.to_fee_src }}
</span>
</div> </div>
<div class="w-full md:w-1/2 p-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">Fee To Increase By</p> <p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Fee To Increase By</p>
<div class="relative"> <div class="relative">
{{ input_down_arrow_offer_svg | safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_rate_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path d="M15.6,13.873a2.273,2.273,0,0,1-.825,1.833,4.1,4.1,0,0,1-2.31.829v1.47h-.982V16.563a7.95,7.95,0,0,1-3.07-.617V14.053a8.328,8.328,0,0,0,1.5.545,8.019,8.019,0,0,0,1.568.28V12.654L11,12.468a5.357,5.357,0,0,1-2.012-1.216A2.332,2.332,0,0,1,8.4,9.627a2.123,2.123,0,0,1,.814-1.71,4.143,4.143,0,0,1,2.27-.812v-1.1h.982V7.074a8.126,8.126,0,0,1,2.97.66l-.674,1.678a7.768,7.768,0,0,0-2.3-.559v2.116a11.073,11.073,0,0,1,1.991.932,2.733,2.733,0,0,1,.867.868A2.146,2.146,0,0,1,15.6,13.873ZM10.558,9.627a.678.678,0,0,0,.219.52,2.569,2.569,0,0,0,.707.42V8.881Q10.559,9.017,10.558,9.627Zm2.884,4.354a.646.646,0,0,0-.244-.509,3.173,3.173,0,0,0-.732-.431v1.786Q13.441,14.662,13.442,13.981Z" stroke="none" fill="#3b82f6"></path>
<polyline points="5.346 7.929 6.932 2.237 1.135 2.966"></polyline>
<path data-cap="butt" d="M11.789,23A11,11,0,0,1,6.932,2.237"></path>
<polyline points="18.654 16.071 17.068 21.763 22.865 21.034"></polyline>
<path data-cap="butt" d="M12.211,1a11,11,0,0,1,4.857,20.763"></path>
</g>
</svg>
</div> </div>
<select class="cursor-not-allowed disabled-select pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="fee_to_extra" disabled> <select class="cursor-not-allowed disabled-select pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="fee_to_extra_" disabled>
<option value="0">None</option> <option value="0">None</option>
<option value="10" {% if data.fee_to_extra==10 %} selected{% endif %}>10%</option> <option value="10" {% if data.fee_from_extra==10 %} selected{% endif %}>10%</option>
<option value="50" {% if data.fee_to_extra==50 %} selected{% endif %}>50%</option> <option value="50" {% if data.fee_from_extra==50 %} selected{% endif %}>50%</option>
<option value="100" {% if data.fee_to_extra==100 %} selected{% endif %}>100%</option> <option value="100" {% if data.fee_from_extra==100 %} selected{% endif %}>100%</option>
</select>
</div>
</div>
{% endif %}
{% if data.swap_style == 'xmr' and coin_to != '6' %}
<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">Fee To Confirm Target</p>
<div class="relative">
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path d="M15.6,13.873a2.273,2.273,0,0,1-.825,1.833,4.1,4.1,0,0,1-2.31.829v1.47h-.982V16.563a7.95,7.95,0,0,1-3.07-.617V14.053a8.328,8.328,0,0,0,1.5.545,8.019,8.019,0,0,0,1.568.28V12.654L11,12.468a5.357,5.357,0,0,1-2.012-1.216A2.332,2.332,0,0,1,8.4,9.627a2.123,2.123,0,0,1,.814-1.71,4.143,4.143,0,0,1,2.27-.812v-1.1h.982V7.074a8.126,8.126,0,0,1,2.97.66l-.674,1.678a7.768,7.768,0,0,0-2.3-.559v2.116a11.073,11.073,0,0,1,1.991.932,2.733,2.733,0,0,1,.867.868A2.146,2.146,0,0,1,15.6,13.873ZM10.558,9.627a.678.678,0,0,0,.219.52,2.569,2.569,0,0,0,.707.42V8.881Q10.559,9.017,10.558,9.627Zm2.884,4.354a.646.646,0,0,0-.244-.509,3.173,3.173,0,0,0-.732-.431v1.786Q13.441,14.662,13.442,13.981Z" stroke="none" fill="#3b82f6"></path>
<polyline points="5.346 7.929 6.932 2.237 1.135 2.966"></polyline>
<path data-cap="butt" d="M11.789,23A11,11,0,0,1,6.932,2.237"></path>
<polyline points="18.654 16.071 17.068 21.763 22.865 21.034"></polyline>
<path data-cap="butt" d="M12.211,1a11,11,0,0,1,4.857,20.763"></path>
</g>
</svg>
</div>
<input class="cursor-not-allowed disabled-input pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" type="number" name="fee_to_conf" min="1" max="32" value="{{ data.fee_from_conf }}" readonly>
</div>
</div>
<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">Fee To Increase By</p>
<div class="relative">
<svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path d="M15.6,13.873a2.273,2.273,0,0,1-.825,1.833,4.1,4.1,0,0,1-2.31.829v1.47h-.982V16.563a7.95,7.95,0,0,1-3.07-.617V14.053a8.328,8.328,0,0,0,1.5.545,8.019,8.019,0,0,0,1.568.28V12.654L11,12.468a5.357,5.357,0,0,1-2.012-1.216A2.332,2.332,0,0,1,8.4,9.627a2.123,2.123,0,0,1,.814-1.71,4.143,4.143,0,0,1,2.27-.812v-1.1h.982V7.074a8.126,8.126,0,0,1,2.97.66l-.674,1.678a7.768,7.768,0,0,0-2.3-.559v2.116a11.073,11.073,0,0,1,1.991.932,2.733,2.733,0,0,1,.867.868A2.146,2.146,0,0,1,15.6,13.873ZM10.558,9.627a.678.678,0,0,0,.219.52,2.569,2.569,0,0,0,.707.42V8.881Q10.559,9.017,10.558,9.627Zm2.884,4.354a.646.646,0,0,0-.244-.509,3.173,3.173,0,0,0-.732-.431v1.786Q13.441,14.662,13.442,13.981Z" stroke="none" fill="#3b82f6"></path>
<polyline points="5.346 7.929 6.932 2.237 1.135 2.966"></polyline>
<path data-cap="butt" d="M11.789,23A11,11,0,0,1,6.932,2.237"></path>
<polyline points="18.654 16.071 17.068 21.763 22.865 21.034"></polyline>
<path data-cap="butt" d="M12.211,1a11,11,0,0,1,4.857,20.763"></path>
</g>
</svg>
</div>
<select class="cursor-not-allowed disabled-input disabled-select pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="fee_to_extra" disabled>
<option value="0">None</option>
<option value="10" {% if data.fee_from_extra==10 %} selected{% endif %}>10%</option>
<option value="50" {% if data.fee_from_extra==50 %} selected{% endif %}>50%</option>
<option value="100" {% if data.fee_from_extra==100 %} selected{% endif %}>100%</option>
</select> </select>
</div> </div>
</div> </div>
@@ -278,10 +475,10 @@
</div> </div>
</div> </div>
</div> </div>
<div class="py-0 border-b items-center justify-between -mx-4 mb-6 pb-3 border-gray-400 border-opacity-20"> <div class="py-3 border-b items-center justify-between -mx-4 mb-6 pb-6 border-gray-400 border-opacity-20">
<div class="w-full md:w-10/12"> <div class="w-full md:w-10/12">
<div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0"> <div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0">
<div class="w-full md:w-1/3 p-6"> <div class="w-full md:w-1/3 p-3">
<p class="text-sm text-coolGray-800 dark:text-white font-semibold">Bid Amount</p> <p class="text-sm text-coolGray-800 dark:text-white font-semibold">Bid Amount</p>
</div> </div>
<div class="w-full md:flex-1 p-3"> <div class="w-full md:flex-1 p-3">
@@ -290,7 +487,16 @@
<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 Bid Amount</p>
<div class="relative"> <div class="relative">
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_bid_amount_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<rect x="9.843" y="5.379" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -0.7635 13.1569)" width="11.314" height="4.243"></rect>
<polyline points="3,23 3,19 15,19 15,23 "></polyline>
<line x1="4" y1="15" x2="1" y2="15" stroke="#3b82f6"></line>
<line x1="5.757" y1="10.757" x2="3.636" y2="8.636" stroke="#3b82f6"></line>
<line x1="1" y1="23" x2="17" y2="23"></line>
<line x1="17" y1="9" x2="23" y2="15"></line>
</g>
</svg>
</div> </div>
<input class="cursor-not-allowed disabled-input pl-10 hover:border-blue-500 pl-10 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-white 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="amt_bid_min" name="amt_bid_min" value="{{ data.amt_bid_min }}" title="Bids with an amount below the minimum bid value will be discarded" readonly> <input class="cursor-not-allowed disabled-input pl-10 hover:border-blue-500 pl-10 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-white 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="amt_bid_min" name="amt_bid_min" value="{{ data.amt_bid_min }}" title="Bids with an amount below the minimum bid value will be discarded" readonly>
</div> </div>
@@ -299,9 +505,16 @@
<p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Rate</p> <p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Rate</p>
<div class="relative"> <div class="relative">
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_rate_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g fill="#3b82f6">
<path d="M9,9h5L7,0,0,9H5V23a1,1,0,0,0,1,1H8a1,1,0,0,0,1-1Z" fill="#3b82f6"></path>
<path d="M14,17a3,3,0,1,1,3-3A3,3,0,0,1,14,17Zm0-4a1,1,0,1,0,1,1A1,1,0,0,0,14,13Z" data-color="color-2"></path>
<path d="M21,24a3,3,0,1,1,3-3A3,3,0,0,1,21,24Zm0-4a1,1,0,1,0,1,1A1,1,0,0,0,21,20Z" data-color="color-2"></path>
<path d="M13,23a1,1,0,0,1-.707-1.707l9-9a1,1,0,0,1,1.414,1.414l-9,9A1,1,0,0,1,13,23Z" data-color="color-2"></path>
</g>
</svg>
</div> </div>
<input class="cursor-not-allowed disabled-input pl-10 hover:border-blue-500 pl-10 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-white 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="rate" name="rate" value="{{ data.rate }}" readonly> <input class="cursor-not-allowed disabled-input pl-10 hover:border-blue-500 pl-10 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-white 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="rate" name="rate" value="{{ data.rate }}" onchange="set_rate('rate');" readonly>
</div> </div>
</div> </div>
</div> </div>
@@ -309,10 +522,10 @@
</div> </div>
</div> </div>
</div> </div>
<div class="py-0 border-b items-center justify-between -mx-4 mb-6 pb-3 border-gray-400 border-opacity-20"> <div class="py-3 border-b items-center justify-between -mx-4 mb-6 pb-6 border-gray-400 border-opacity-20">
<div class="w-full md:w-10/12"> <div class="w-full md:w-10/12">
<div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0"> <div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0">
<div class="w-full md:w-1/3 p-6"> <div class="w-full md:w-1/3 p-3">
<p class="text-sm text-coolGray-800 dark:text-white font-semibold">Time</p> <p class="text-sm text-coolGray-800 dark:text-white font-semibold">Time</p>
</div> </div>
<div class="w-full md:flex-1 p-3"> <div class="w-full md:flex-1 p-3">
@@ -321,7 +534,15 @@
<p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Offer valid (hrs)</p> <p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Offer valid (hrs)</p>
<div class="relative"> <div class="relative">
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ input_time_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path d="M15.6,13.873a2.273,2.273,0,0,1-.825,1.833,4.1,4.1,0,0,1-2.31.829v1.47h-.982V16.563a7.95,7.95,0,0,1-3.07-.617V14.053a8.328,8.328,0,0,0,1.5.545,8.019,8.019,0,0,0,1.568.28V12.654L11,12.468a5.357,5.357,0,0,1-2.012-1.216A2.332,2.332,0,0,1,8.4,9.627a2.123,2.123,0,0,1,.814-1.71,4.143,4.143,0,0,1,2.27-.812v-1.1h.982V7.074a8.126,8.126,0,0,1,2.97.66l-.674,1.678a7.768,7.768,0,0,0-2.3-.559v2.116a11.073,11.073,0,0,1,1.991.932,2.733,2.733,0,0,1,.867.868A2.146,2.146,0,0,1,15.6,13.873ZM10.558,9.627a.678.678,0,0,0,.219.52,2.569,2.569,0,0,0,.707.42V8.881Q10.559,9.017,10.558,9.627Zm2.884,4.354a.646.646,0,0,0-.244-.509,3.173,3.173,0,0,0-.732-.431v1.786Q13.441,14.662,13.442,13.981Z" stroke="none" fill="#3b82f6"></path>
<polyline points="5.346 7.929 6.932 2.237 1.135 2.966"></polyline>
<path data-cap="butt" d="M11.789,23A11,11,0,0,1,6.932,2.237"></path>
<polyline points="18.654 16.071 17.068 21.763 22.865 21.034"></polyline>
<path data-cap="butt" d="M12.211,1a11,11,0,0,1,4.857,20.763"></path>
</g>
</svg>
</div> </div>
<input class="cursor-not-allowed disabled-input pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" type="number" name="validhrs" min="1" max="48" value="{{ data.validhrs }}" readonly> <input class="cursor-not-allowed disabled-input pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" type="number" name="validhrs" min="1" max="48" value="{{ data.validhrs }}" readonly>
</div> </div>
@@ -331,7 +552,15 @@
<p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Contract Locked (Mins)</p> <p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Contract Locked (Mins)</p>
<div class="relative"> <div class="relative">
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ input_time_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path d="M15.6,13.873a2.273,2.273,0,0,1-.825,1.833,4.1,4.1,0,0,1-2.31.829v1.47h-.982V16.563a7.95,7.95,0,0,1-3.07-.617V14.053a8.328,8.328,0,0,0,1.5.545,8.019,8.019,0,0,0,1.568.28V12.654L11,12.468a5.357,5.357,0,0,1-2.012-1.216A2.332,2.332,0,0,1,8.4,9.627a2.123,2.123,0,0,1,.814-1.71,4.143,4.143,0,0,1,2.27-.812v-1.1h.982V7.074a8.126,8.126,0,0,1,2.97.66l-.674,1.678a7.768,7.768,0,0,0-2.3-.559v2.116a11.073,11.073,0,0,1,1.991.932,2.733,2.733,0,0,1,.867.868A2.146,2.146,0,0,1,15.6,13.873ZM10.558,9.627a.678.678,0,0,0,.219.52,2.569,2.569,0,0,0,.707.42V8.881Q10.559,9.017,10.558,9.627Zm2.884,4.354a.646.646,0,0,0-.244-.509,3.173,3.173,0,0,0-.732-.431v1.786Q13.441,14.662,13.442,13.981Z" stroke="none" fill="#3b82f6"></path>
<polyline points="5.346 7.929 6.932 2.237 1.135 2.966"></polyline>
<path data-cap="butt" d="M11.789,23A11,11,0,0,1,6.932,2.237"></path>
<polyline points="18.654 16.071 17.068 21.763 22.865 21.034"></polyline>
<path data-cap="butt" d="M12.211,1a11,11,0,0,1,4.857,20.763"></path>
</g>
</svg>
</div> </div>
<input class="cursor-not-allowed disabled-input pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" type="number" name="lockmins" min="10" max="5000" value="{{ data.lockmins }}" readonly> <input class="cursor-not-allowed disabled-input pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" type="number" name="lockmins" min="10" max="5000" value="{{ data.lockmins }}" readonly>
</div> </div>
@@ -344,7 +573,15 @@
<p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Contract locked (Hours)</p> <p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Contract locked (Hours)</p>
<div class="relative"> <div class="relative">
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ input_time_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path d="M15.6,13.873a2.273,2.273,0,0,1-.825,1.833,4.1,4.1,0,0,1-2.31.829v1.47h-.982V16.563a7.95,7.95,0,0,1-3.07-.617V14.053a8.328,8.328,0,0,0,1.5.545,8.019,8.019,0,0,0,1.568.28V12.654L11,12.468a5.357,5.357,0,0,1-2.012-1.216A2.332,2.332,0,0,1,8.4,9.627a2.123,2.123,0,0,1,.814-1.71,4.143,4.143,0,0,1,2.27-.812v-1.1h.982V7.074a8.126,8.126,0,0,1,2.97.66l-.674,1.678a7.768,7.768,0,0,0-2.3-.559v2.116a11.073,11.073,0,0,1,1.991.932,2.733,2.733,0,0,1,.867.868A2.146,2.146,0,0,1,15.6,13.873ZM10.558,9.627a.678.678,0,0,0,.219.52,2.569,2.569,0,0,0,.707.42V8.881Q10.559,9.017,10.558,9.627Zm2.884,4.354a.646.646,0,0,0-.244-.509,3.173,3.173,0,0,0-.732-.431v1.786Q13.441,14.662,13.442,13.981Z" stroke="none" fill="#3b82f6"></path>
<polyline points="5.346 7.929 6.932 2.237 1.135 2.966"></polyline>
<path data-cap="butt" d="M11.789,23A11,11,0,0,1,6.932,2.237"></path>
<polyline points="18.654 16.071 17.068 21.763 22.865 21.034"></polyline>
<path data-cap="butt" d="M12.211,1a11,11,0,0,1,4.857,20.763"></path>
</g>
</svg>
</div> </div>
<input class="cursor-not-allowed disabled-input pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" type="number" name="lockhrs" min="1" max="96" value="{{ data.lockhrs }}" readonly> <input class="cursor-not-allowed disabled-input pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" type="number" name="lockhrs" min="1" max="96" value="{{ data.lockhrs }}" readonly>
</div> </div>
@@ -358,10 +595,10 @@
</div> </div>
</div> </div>
</div> </div>
<div class="py-0 border-b items-center justify-between -mx-4 mb-6 pb-3 border-gray-400 border-opacity-20"> <div class="py-3 border-b items-center justify-between -mx-4 mb-6 pb-6 border-gray-400 border-opacity-20">
<div class="w-full md:w-10/12"> <div class="w-full md:w-10/12">
<div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0"> <div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0">
<div class="w-full md:w-1/3 p-6"> <div class="w-full md:w-1/3 p-3">
<p class="text-sm text-coolGray-800 dark:text-white font-semibold">Strategy</p> <p class="text-sm text-coolGray-800 dark:text-white font-semibold">Strategy</p>
</div> </div>
<div class="w-full md:flex-1 p-3"> <div class="w-full md:flex-1 p-3">
@@ -369,9 +606,21 @@
<div class="w-full md:w-1/2 p-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">Auto Accept Strategy</p> <p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Auto Accept Strategy</p>
<div class="relative"> <div class="relative">
{{ input_down_arrow_offer_svg | safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_auto_strategy_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<circle cx="12" cy="12" r="5" stroke="#3b82f6" data-cap="butt"></circle>
<polygon points="5 6 2 4 5 2 5 6" fill="#3b82f6" stroke="none"></polygon>
<polygon points="19 18 22 20 19 22 19 18" fill="#3b82f6" stroke="none"></polygon>
<polygon points="5 6 2 4 5 2 5 6"></polygon>
<line x1="5" y1="4" x2="9" y2="4"></line>
<polygon points="19 18 22 20 19 22 19 18"></polygon>
<line x1="19" y1="20" x2="15" y2="20"></line>
</g>
</svg>
</div> </div>
<select class="cursor-not-allowed disabled-select pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="automation_strat_id" disabled> <select class="cursor-not-allowed disabled-select pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="automation_strat_id" disabled>
<option value="-1" {% if data.automation_strat_id==-1 %} selected{% endif %}>None</option> <option value="-1" {% if data.automation_strat_id==-1 %} selected{% endif %}>None</option>
@@ -386,26 +635,20 @@
</div> </div>
</div> </div>
</div> </div>
<div class="py-0 border-b items-center justify-between -mx-4 mb-6 pb-3 border-gray-400 border-opacity-20"> <div class="py-3 border-b items-center justify-between -mx-4 mb-6 pb-6 border-gray-400 border-opacity-20">
<div class="w-full md:w-10/12"> <div class="w-full md:w-10/12">
<div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0"> <div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0">
<div class="w-full md:w-1/3 p-6"> <div class="w-full md:w-1/3 p-3">
<p class="text-sm text-coolGray-800 dark:text-white font-semibold">Options</p> <p class="text-sm text-coolGray-800 dark:text-white font-semibold">Options</p>
</div> </div>
<div class="w-full md:flex-1 p-3"> <div class="w-full md:flex-1 p-3">
<div class="flex form-check form-check-inline"> <div class="form-check form-check-inline">
<div class="flex items-center h-5"> <input class="cursor-not-allowed 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="amt_var" name="amt_var" value="av" {% if data.amt_var==true %} checked="checked" {% endif %} disabled> </div> <input class="cursor-not-allowed disabled-input 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="amt_var" name="amt_var" value="av" {% if data.amt_var==true %} checked="checked" {% endif %} disabled>
<div class="ml-2 text-sm"> <label class="form-check-label ml-2 text-sm font-medium text-gray-800 dark:text-white" for="inlineCheckbox2">Amount Variable</label>
<label class="form-check-label text-sm font-medium text-gray-800 dark:text-white" for="inlineCheckbox2" style="opacity: 0.40;">Amount Variable</label>
<p id="helper-checkbox-text" class="text-xs font-normal text-gray-500 dark:text-gray-300" style="opacity: 0.40;">Allow bids with a different amount to the offer.</p>
</div>
</div>
<div class="flex mt-2 form-check form-check-inline">
<div class="flex items-center h-5"> <input class="cursor-not-allowed 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="rate_var" name="rate_var" value="rv" {% if data.rate_var==true %} checked="checked" {% endif %} disabled> </div>
<div class="ml-2 text-sm">
<label class="form-check-label text-sm font-medium text-gray-800 dark:text-white" for="inlineCheckbox3" style="opacity: 0.40;">Rate Variable</label>
<p id="helper-checkbox-text" class="text-xs font-normal text-gray-500 dark:text-gray-300" style="opacity: 0.40;">Allow bids with a different rate to the offer.</p>
</div> </div>
<div class="form-check form-check-inline mt-2">
<input class="cursor-not-allowed disabled-input 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="rate_var" name="rate_var" value="rv" {% if data.rate_var==true %} checked="checked" {% endif %} disabled>
<label class="form-check-label ml-2 text-sm font-medium text-gray-800 dark:text-white" for="inlineCheckbox3">Rate Variable</label>
</div> </div>
</div> </div>
</div> </div>
@@ -425,12 +668,19 @@
<div class="flex flex-wrap justify-end"> <div class="flex flex-wrap justify-end">
<div class="w-full md:w-auto p-1.5"> <div class="w-full md:w-auto p-1.5">
<button name="step2" type="submit" value="Back" class="flex flex-wrap justify-center w-full px-4 py-2.5 font-medium text-sm text-coolGray-500 hover:text-coolGray-600 border border-coolGray-200 hover:border-coolGray-300 bg-white rounded-md focus:ring-0 focus:outline-none dark:text-white dark:hover:text-white dark:bg-gray-600 dark:hover:bg-gray-700 dark:border-gray-600 dark:hover:border-gray-600"> <button name="step2" type="submit" value="Back" class="flex flex-wrap justify-center w-full px-4 py-2.5 font-medium text-sm text-coolGray-500 hover:text-coolGray-600 border border-coolGray-200 hover:border-coolGray-300 bg-white rounded-md focus:ring-0 focus:outline-none dark:text-white dark:hover:text-white dark:bg-gray-600 dark:hover:bg-gray-700 dark:border-gray-600 dark:hover:border-gray-600">
</svg>
<span>Back</span> <span>Back</span>
</button> </button>
</div> </div>
<div class="w-full md:w-auto p-1.5"> <div class="w-full md:w-auto p-1.5">
<button name="submit_offer" value="Continue" type="submit" class="flex flex-wrap justify-center w-full px-4 py-2.5 bg-blue-500 hover:bg-green-600 hover:border-green-600 font-medium text-sm text-white border border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none"> <button name="submit_offer" value="Continue" 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">
<span>Confirm</span> <svg class="mr-2" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
<circle cx="12" cy="12" r="11"></circle>
<polyline points="11 8 15 12 11 16" stroke="#ffffff"></polyline>
</g>
</svg>
<span>Confirm Offer</span>
</button> </button>
</div> </div>
</div> </div>
@@ -442,6 +692,35 @@
</div> </div>
</div> </div>
</section> </section>
<script>
const selects = document.querySelectorAll('select.disabled-select');
for (const select of selects) {
if (select.disabled) {
select.classList.add('disabled-select-enabled');
} else {
select.classList.remove('disabled-select-enabled');
}
}
</script>
<script>
const inputs = document.querySelectorAll('input.disabled-input, input[type="checkbox"].disabled-input');
for (const input of inputs) {
if (input.readOnly) {
input.classList.add('disabled-input-enabled');
} else {
input.classList.remove('disabled-input-enabled');
}
}
</script>
<style>
.disabled-input-enabled {
opacity: 0.50 !important;
}
select.disabled-select-enabled {
opacity: 0.50 !important;
}
</style>
<input type="hidden" name="formid" value="{{ form_id }}"> <input type="hidden" name="formid" value="{{ form_id }}">
<input type="hidden" name="addr_to" value="{{ data.addr_to }}"> <input type="hidden" name="addr_to" value="{{ data.addr_to }}">
<input type="hidden" name="addr_from" value="{{ data.addr_from }}"> <input type="hidden" name="addr_from" value="{{ data.addr_from }}">
@@ -458,9 +737,12 @@
{% endif %} {% endif %}
{% if data.rate_var==true %} {% if data.rate_var==true %}
<input type="hidden" name="rate_var" value="rv"> <input type="hidden" name="rate_var" value="rv">
{% endif %} {% endif %}
</form> </form>
<script src="static/js/new_offer.js"></script> <!-- ?? -->
<script src="static/js/new_offer.js"></script>
<script src="static/js/coin_icons.js"></script>
<script src="static/js/coin_icons_2.js"></script>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,17 +1,27 @@
{% include 'header.html' %} {% from 'style.html' import breadcrumb_line_svg, input_down_arrow_offer_svg, select_network_svg, select_address_svg, select_swap_type_svg, select_bid_amount_svg, select_rate_svg, step_one_svg, step_two_svg, step_three_svg %} {% include 'header.html' %}
<script src="static/js/coin_icons.js"></script>
<div class="container mx-auto"> <div class="container mx-auto">
<section class="p-5 mt-5"> <section class="p-5 mt-5">
<div class="flex flex-wrap items-center -m-2"> <div class="flex flex-wrap items-center -m-2">
<div class="w-full md:w-1/2 p-2"> <div class="w-full md:w-1/2 p-2">
<ul class="flex flex-wrap items-center gap-x-3 mb-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="/"> <li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/">
<p>Home</p> <p>Home</p>
</a> </a>
</li> </li>
<li>{{ breadcrumb_line_svg | safe }}</li> <li>
<li><a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/newoffer">Place</a></li> <svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<li>{{ breadcrumb_line_svg | safe }}</li> <path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
<li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/newoffer">Place an new offer</a>
</li>
<li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
</ul> </ul>
</div> </div>
</div> </div>
@@ -24,8 +34,8 @@
<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=""> <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="">
<div class="relative z-20 flex flex-wrap items-center -m-3"> <div class="relative z-20 flex flex-wrap items-center -m-3">
<div class="w-full md:w-1/2 p-3"> <div class="w-full md:w-1/2 p-3">
<h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">Place an New Offer</h2> <h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">Place an new offer</h2>
<p class="font-normal text-coolGray-200 dark:text-white">Place an order on the network order book.</p> <p class="font-normal text-coolGray-200 dark:text-white">Place an order on the order book.</p>
</div> </div>
</div> </div>
</div> </div>
@@ -33,35 +43,41 @@
</section> </section>
{% include 'inc_messages.html' %} {% include 'inc_messages.html' %}
<section> <section>
<div class="p-5 mb-5"> <div class="p-5 mb-10">
<div class="mx-4 p-4"> <div class="mx-4 p-4">
<div class="flex items-center"> <div class="flex items-center">
<div class="flex items-center text-teal-600 relative"> <div class="flex items-center text-teal-600 relative">
<div class="rounded-full h-12 w-12 py-3 border-2 border-blue-500"> <div class="rounded-full h-12 w-12 py-3 border-2 border-blue-500">
{{ step_one_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 24 24">
<g fill="#3b82f6">
<polygon points="14.5 23.5 11.5 23.5 11.5 4.321 6.766 8.108 4.892 5.766 11.474 0.5 14.5 0.5 14.5 23.5" fill="#3b82f6"></polygon>
</g>
</svg>
</div> </div>
<div class="absolute top-0 -ml-10 text-center mt-16 w-32 text-xs font-medium uppercase dark:text-white text-gray-700">Step 1 - Place</div> <div class="absolute top-0 -ml-10 text-center mt-16 w-32 text-xs font-medium uppercase dark:text-white text-gray-600">Step 1</div>
</div> </div>
<div class="flex-auto border-t-2 border-teal-600 dark:border-gray-400"></div>
<div class="flex-auto border-t-2 border-gray-300 dark:border-gray-400"></div>
<div class="flex items-center text-teal-600 relative"> <div class="flex items-center text-teal-600 relative">
<div class="rounded-full transition duration-500 ease-in-out h-12 w-12 py-3 border-2 border-gray-300 dark:border-gray-400"> <div class="rounded-full transition duration-500 ease-in-out h-12 w-12 py-3 border-2 border-teal-600 dark:border-gray-400">
{{ step_two_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 24 24">
<g fill="#3b82f6">
<path d="M19.5,23.5H4.5V20.2l.667-.445C9.549,16.828,16.5,10.78,16.5,7c0-2.654-1.682-4-5-4A9.108,9.108,0,0,0,7.333,4.248L6.084,5.08,4.42,2.584l1.247-.832A11.963,11.963,0,0,1,11.5,0c4.935,0,8,2.683,8,7,0,5-6.5,10.662-10.232,13.5H19.5ZM6,21H6Z" fill="#d1d5db"></path>
</g>
</svg>
</div> </div>
<div class="absolute top-0 -ml-10 text-center mt-16 w-32 text-xs font-medium uppercase dark:text-white text-gray-700">Step 2 - Setup</div> <div class="absolute top-0 -ml-10 text-center mt-16 w-32 text-xs font-medium uppercase dark:text-white text-gray-600">Step 2</div>
</div> </div>
<div class="flex-auto border-t-2 border-teal-600 dark:border-gray-400"></div>
<div class="flex-auto border-t-2 border-gray-300 dark:border-gray-400"></div>
<div class="flex items-center text-gray-500 relative"> <div class="flex items-center text-gray-500 relative">
<div class="rounded-full transition duration-500 ease-in-out h-12 w-12 py-3 border-2 border-gray-300 dark:border-gray-400"> <div class="rounded-full transition duration-500 ease-in-out h-12 w-12 py-3 border-2 border-teal-600 dark:border-gray-400">
{{ step_three_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 24 24">
<g fill="#3b82f6">
<polygon points="9 21 1 13 4 10 9 15 21 3 24 6 9 21" fill="#d1d5db"></polygon>
</g>
</svg>
</div> </div>
<div class="absolute top-0 -ml-10 text-center mt-16 w-32 text-xs font-medium uppercase dark:text-white text-gray-700">Confirm</div> <div class="absolute top-0 -ml-10 text-center mt-16 w-32 text-xs font-medium uppercase dark:text-white text-gray-600">Confirm</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
@@ -69,19 +85,34 @@
<section class="py-3"> <section class="py-3">
<div class="container px-4 mx-auto"> <div class="container px-4 mx-auto">
<div class="p-8 bg-coolGray-100 dark:bg-gray-500 rounded-xl"> <div class="p-8 bg-coolGray-100 dark:bg-gray-500 rounded-xl">
<div class="flex flex-wrap items-center justify-between -mx-4 pb-6 border-gray-400 border-opacity-20"> </div> <div class="flex flex-wrap items-center justify-between -mx-4 mb-8 pb-6 border-b border-gray-400 border-opacity-20">
<div class="w-full sm:w-auto px-4 mb-6 sm:mb-0">
<h4 class="text-2xl font-bold tracking-wide dark:text-white mb-1">STEP 1</h4>
<!-- todo add subtitle <p class="text-sm text-coolGray-500">Lorem ipsum dolor sit amet</p> -->
</div>
</div>
<form method="post" autocomplete="off" id='form'> <form method="post" autocomplete="off" id='form'>
<div class="py-3 border-b items-center justify-between -mx-4 mb-6 pb-3 border-gray-400 border-opacity-20"> <div class="py-3 border-b items-center justify-between -mx-4 mb-6 pb-6 border-gray-400 border-opacity-20">
<div class="w-full md:w-10/12"> <div class="w-full md:w-10/12">
<div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0"> <div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0">
<div class="w-full md:w-1/3 p-6"> <div class="w-full md:w-1/3 p-3">
<p class="text-sm text-coolGray-800 dark:text-white font-semibold">Select Network</p> <p class="text-sm text-coolGray-800 dark:text-white font-semibold">Select Network</p>
</div> </div>
<div class="w-full md:flex-1 p-3"> <div class="w-full md:flex-1 p-3">
<div class="relative"> <div class="relative">
{{ input_down_arrow_offer_svg | safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_network_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<line data-cap="butt" x1="7.6" y1="10.5" x2="16.4" y2="5.5" stroke="#3b82f6"></line>
<line data-cap="butt" x1="7.6" y1="13.5" x2="16.4" y2="18.5" stroke="#3b82f6"></line>
<circle cx="5" cy="12" r="3"></circle>
<circle cx="19" cy="4" r="3"></circle>
<circle cx="19" cy="20" r="3"></circle>
</g>
</svg>
</div> </div>
<select class="pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="addr_to"> <select class="pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="addr_to">
<option{% if data.addr_to=="-1" %} selected{% endif %} value="-1">Public Network</option> <option{% if data.addr_to=="-1" %} selected{% endif %} value="-1">Public Network</option>
@@ -94,19 +125,28 @@
</div> </div>
</div> </div>
</div> </div>
<div class="py-0 border-b items-center justify-between -mx-4 mb-6 pb-3 border-gray-400 border-opacity-20"> <div class="py-3 border-b items-center justify-between -mx-4 mb-6 pb-6 border-gray-400 border-opacity-20">
<div class="w-full md:w-10/12"> <div class="w-full md:w-10/12">
<div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0"> <div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0">
<div class="w-full md:w-1/3 p-6"> <div class="w-full md:w-1/3 p-3">
<p class="text-sm text-coolGray-800 dark:text-white font-semibold">Select Address</p> <p class="text-sm text-coolGray-800 dark:text-white font-semibold">Select Address</p>
</div> </div>
<div class="w-full md:flex-1 p-3"> <div class="w-full md:flex-1 p-3">
<div class="relative"> <div class="relative">
{{ input_down_arrow_offer_svg | safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_address_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path data-cap="butt" d="M11.992,11.737,14.2,13.4A2,2,0,0,1,15,15v1H7V15a2,2,0,0,1,.8-1.6l2.208-1.663" stroke="#3b82f6"></path>
<rect x="9" y="7" width="4" height="5" rx="2" ry="2" stroke="#3b82f6"></rect>
<path d="M2,1H18a2,2,0,0,1,2,2V21a2,2,0,0,1-2,2H2Z"></path>
<line x1="23" y1="5" x2="23" y2="9" stroke="#3b82f6"></line>
</g>
</svg>
</div> </div>
<select class="hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="addr_from"> <select class="pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="addr_from">
{% for a in addrs %} {% for a in addrs %}
<option{% if data.addr_from==a[0] %} selected{% endif %} value="{{ a[0] }}">{{ a[0] }} {{ a[1] }}</option> <option{% if data.addr_from==a[0] %} selected{% endif %} value="{{ a[0] }}">{{ a[0] }} {{ a[1] }}</option>
{% endfor %} {% endfor %}
@@ -117,19 +157,28 @@
</div> </div>
</div> </div>
</div> </div>
<div class="py-0 border-b items-center justify-between -mx-4 mb-6 pb-3 border-gray-400 border-opacity-20"> <div class="py-3 border-b items-center justify-between -mx-4 mb-6 pb-6 border-gray-400 border-opacity-20">
<div class="w-full md:w-10/12"> <div class="w-full md:w-10/12">
<div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0"> <div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0">
<div class="w-full md:w-1/3 p-6"> <div class="w-full md:w-1/3 p-3">
<p class="text-sm text-coolGray-800 dark:text-white font-semibold">Swap Type</p> <p class="text-sm text-coolGray-800 dark:text-white font-semibold">Swap Type</p>
</div> </div>
<div class="w-full md:flex-1 p-3"> <div class="w-full md:flex-1 p-3">
<div class="relative"> <div class="relative">
{{ input_down_arrow_offer_svg | safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_swap_type_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path data-cap="butt" d="M11.992,11.737,14.2,13.4A2,2,0,0,1,15,15v1H7V15a2,2,0,0,1,.8-1.6l2.208-1.663" stroke="#3b82f6"></path>
<rect x="9" y="7" width="4" height="5" rx="2" ry="2" stroke="#3b82f6"></rect>
<path d="M2,1H18a2,2,0,0,1,2,2V21a2,2,0,0,1-2,2H2Z"></path>
<line x1="23" y1="5" x2="23" y2="9" stroke="#3b82f6"></line>
</g>
</svg>
</div> </div>
<select class="hover:border-blue-500 bg-gray-50 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="swap_type" id="swap_type"> <select class="pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="swap_type" id="swap_type">
{% for a in swap_types %} {% for a in swap_types %}
<option{% if data.swap_type==a[0] %} selected{% endif %} value="{{ a[0] }}">{{ a[1] }}</option> <option{% if data.swap_type==a[0] %} selected{% endif %} value="{{ a[0] }}">{{ a[1] }}</option>
{% endfor %} {% endfor %}
@@ -139,78 +188,107 @@
</div> </div>
</div> </div>
</div> </div>
<div class="py-0 border-b items-center justify-between -mx-4 mb-6 pb-3 border-gray-400 border-opacity-20">
<div class="py-3 border-b items-center justify-between -mx-4 mb-6 pb-6 border-gray-400 border-opacity-20">
<div class="w-full md:w-10/12"> <div class="w-full md:w-10/12">
<div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0"> <div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0">
<div class="w-full md:w-1/3 p-6"> <div class="w-full md:w-1/3 p-3">
<p class="text-sm text-coolGray-800 dark:text-white font-semibold">You Send</p> <p class="text-sm text-coolGray-800 dark:text-white font-semibold">You Send</p>
</div> </div>
<div class="w-full md:flex-1 p-3"> <div class="w-full md:flex-1 p-3">
<div class="flex flex-wrap -m-3"> <div class="flex flex-wrap -m-3">
<div class="w-full md:w-1/2 p-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">Select Coin You Send</p>
<div class="custom-select"> <div class="custom-select">
<div class="relative"> <div class="relative">
{{ input_down_arrow_offer_svg | safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2 z-50" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<select class="select hover:border-blue-500 pl-10 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-5 bold focus:ring-0" id="coin_from" name="coin_from" onchange="set_rate('coin_from');"> <path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<select class="select hover:border-blue-500 pl-10 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="coin_from" name="coin_from" onchange="set_rate('coin_from');">
<option value="-1">Select coin you send</option> <option value="-1">Select coin you send</option>
{% for c in coins_from %} {% for c in coins_from %}
<option{% if data.coin_from==c[0] %} selected{% endif %} value="{{ c[0] }}" data-image="/static/images/coins/{{ c[1]|replace(" ", "-") }}-20.png">{{ c[1] }}</option> <option{% if data.coin_from==c[0] %} selected{% endif %} value="{{ c[0] }}" data-image="/static/images/coins/{{ c[1]|replace(" ", "-") }}-20.png">{{ c[1] }}</option>
{% endfor %} {% endfor %}
</select> </select>
<div class="select-dropdown"> <img class="select-icon" src="" alt=""> <img class="select-image" src="" alt=""> </div> <div class="select-dropdown">
<img class="select-icon" src="" alt="">
<img class="select-image" src="" alt="">
</div>
</div> </div>
</div> </div>
</div> </div>
<div class="w-full md:w-1/2 p-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">Amount You Send</p>
<div class="relative"> <div class="relative">
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> </div> <input 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-5 focus:ring-0 bold" placeholder="0" type="text" id="amt_from" name="amt_from" value="{{ data.amt_from }}" onchange="set_rate('amt_from');"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path d="M15.6,13.873a2.273,2.273,0,0,1-.825,1.833,4.1,4.1,0,0,1-2.31.829v1.47h-.982V16.563a7.95,7.95,0,0,1-3.07-.617V14.053a8.328,8.328,0,0,0,1.5.545,8.019,8.019,0,0,0,1.568.28V12.654L11,12.468a5.357,5.357,0,0,1-2.012-1.216A2.332,2.332,0,0,1,8.4,9.627a2.123,2.123,0,0,1,.814-1.71,4.143,4.143,0,0,1,2.27-.812v-1.1h.982V7.074a8.126,8.126,0,0,1,2.97.66l-.674,1.678a7.768,7.768,0,0,0-2.3-.559v2.116a11.073,11.073,0,0,1,1.991.932,2.733,2.733,0,0,1,.867.868A2.146,2.146,0,0,1,15.6,13.873ZM10.558,9.627a.678.678,0,0,0,.219.52,2.569,2.569,0,0,0,.707.42V8.881Q10.559,9.017,10.558,9.627Zm2.884,4.354a.646.646,0,0,0-.244-.509,3.173,3.173,0,0,0-.732-.431v1.786Q13.441,14.662,13.442,13.981Z" stroke="none" fill="#3b82f6"></path>
<polyline points="5.346 7.929 6.932 2.237 1.135 2.966"></polyline>
<path data-cap="butt" d="M11.789,23A11,11,0,0,1,6.932,2.237"></path>
<polyline points="18.654 16.071 17.068 21.763 22.865 21.034"></polyline>
<path data-cap="butt" d="M12.211,1a11,11,0,0,1,4.857,20.763"></path>
</g>
</svg>
</div>
<input class="pl-10 hover:border-blue-500 pl-10 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" placeholder="Amount you send" type="text" id="amt_from" name="amt_from" value="{{ data.amt_from }}" onchange="set_rate('amt_from');">
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="py-0 border-b items-center justify-between -mx-4 mb-6 pb-3 border-gray-400 border-opacity-20"> <div class="py-3 border-b items-center justify-between -mx-4 mb-6 pb-6 border-gray-400 border-opacity-20">
<div class="w-full md:w-10/12"> <div class="w-full md:w-10/12">
<div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0"> <div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0">
<div class="w-full md:w-1/3 p-6"> <div class="w-full md:w-1/3 p-3">
<p class="text-sm text-coolGray-800 dark:text-white font-semibold">You Get</p> <p class="text-sm text-coolGray-800 dark:text-white font-semibold">You Get</p>
</div> </div>
<div class="w-full md:flex-1 p-3"> <div class="w-full md:flex-1 p-3">
<div class="flex flex-wrap -m-3"> <div class="flex flex-wrap -m-3">
<div class="w-full md:w-1/2 p-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">Select Coin You Get</p>
<div class="custom-select"> <div class="custom-select">
<div class="relative"> <div class="relative">
{{ input_down_arrow_offer_svg | safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2 z-50" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<select class="select hover:border-blue-500 pl-10 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-5 bold focus:ring-0" id="coin_to" name="coin_to" onchange="set_rate('coin_to');"> <path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<select class="select hover:border-blue-500 pl-10 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="coin_to" name="coin_to" onchange="set_rate('coin_to');">
<option value="-1">Select coin you get</option> <option value="-1">Select coin you get</option>
{% for c in coins %} {% for c in coins %}
<option{% if data.coin_to==c[0] %} selected{% endif %} value="{{ c[0] }}" data-image="/static/images/coins/{{ c[1]|replace(" ", "-") }}-20.png">{{ c[1] }}</option> <option{% if data.coin_to==c[0] %} selected{% endif %} value="{{ c[0] }}" data-image="/static/images/coins/{{ c[1]|replace(" ", "-") }}-20.png">{{ c[1] }}</option>
{% endfor %} {% endfor %}
</select> </select>
<div class="select-dropdown"> <img class="select-icon" src="" alt=""> <img class="select-image" src="" alt=""> </div> <div class="select-dropdown">
<img class="select-icon" src="" alt="">
<img class="select-image" src="" alt="">
</div>
</div> </div>
</div> </div>
</div> </div>
<div class="w-full md:w-1/2 p-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">Amount You Get</p>
<div class="relative"> <div class="relative">
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> </div> <input 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-5 focus:ring-0 bold" placeholder="0" type="text" id="amt_to" name="amt_to" value="{{ data.amt_to }}" onchange="set_rate('amt_to');"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path d="M15.6,13.873a2.273,2.273,0,0,1-.825,1.833,4.1,4.1,0,0,1-2.31.829v1.47h-.982V16.563a7.95,7.95,0,0,1-3.07-.617V14.053a8.328,8.328,0,0,0,1.5.545,8.019,8.019,0,0,0,1.568.28V12.654L11,12.468a5.357,5.357,0,0,1-2.012-1.216A2.332,2.332,0,0,1,8.4,9.627a2.123,2.123,0,0,1,.814-1.71,4.143,4.143,0,0,1,2.27-.812v-1.1h.982V7.074a8.126,8.126,0,0,1,2.97.66l-.674,1.678a7.768,7.768,0,0,0-2.3-.559v2.116a11.073,11.073,0,0,1,1.991.932,2.733,2.733,0,0,1,.867.868A2.146,2.146,0,0,1,15.6,13.873ZM10.558,9.627a.678.678,0,0,0,.219.52,2.569,2.569,0,0,0,.707.42V8.881Q10.559,9.017,10.558,9.627Zm2.884,4.354a.646.646,0,0,0-.244-.509,3.173,3.173,0,0,0-.732-.431v1.786Q13.441,14.662,13.442,13.981Z" stroke="none" fill="#3b82f6"></path>
<polyline points="5.346 7.929 6.932 2.237 1.135 2.966"></polyline>
<path data-cap="butt" d="M11.789,23A11,11,0,0,1,6.932,2.237"></path>
<polyline points="18.654 16.071 17.068 21.763 22.865 21.034"></polyline>
<path data-cap="butt" d="M12.211,1a11,11,0,0,1,4.857,20.763"></path>
</g>
</svg>
</div>
<input class="pl-10 hover:border-blue-500 pl-10 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" placeholder="Amount you get" type="text" id="amt_to" name="amt_to" value="{{ data.amt_to }}" onchange="set_rate('amt_to');">
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="py-0 border-b items-center justify-between -mx-4 mb-6 pb-3 border-gray-400 border-opacity-20"> <div class="py-3 border-b items-center justify-between -mx-4 mb-6 pb-6 border-gray-400 border-opacity-20">
<div class="w-full md:w-10/12"> <div class="w-full md:w-10/12">
<div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0"> <div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0">
<div class="w-full md:w-1/3 p-6"> <div class="w-full md:w-1/3 p-3">
<p class="text-sm text-coolGray-800 dark:text-white font-semibold">Bid Amount</p> <p class="text-sm text-coolGray-800 dark:text-white font-semibold">Bid Amount</p>
</div> </div>
<div class="w-full md:flex-1 p-3"> <div class="w-full md:flex-1 p-3">
@@ -219,7 +297,16 @@
<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 Bid Amount</p>
<div class="relative"> <div class="relative">
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_bid_amount_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<rect x="9.843" y="5.379" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -0.7635 13.1569)" width="11.314" height="4.243"></rect>
<polyline points="3,23 3,19 15,19 15,23 "></polyline>
<line x1="4" y1="15" x2="1" y2="15" stroke="#3b82f6"></line>
<line x1="5.757" y1="10.757" x2="3.636" y2="8.636" stroke="#3b82f6"></line>
<line x1="1" y1="23" x2="17" y2="23"></line>
<line x1="17" y1="9" x2="23" y2="15"></line>
</g>
</svg>
</div> </div>
<input class="pl-10 hover:border-blue-500 pl-10 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-white 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="amt_bid_min" name="amt_bid_min" value="{{ data.amt_bid_min }}" title="Bids with an amount below the minimum bid value will be discarded"> <input class="pl-10 hover:border-blue-500 pl-10 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-white 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="amt_bid_min" name="amt_bid_min" value="{{ data.amt_bid_min }}" title="Bids with an amount below the minimum bid value will be discarded">
</div> </div>
@@ -228,55 +315,70 @@
<p class="mb-1.5 font-medium text-base dark:text-white text-coolGray-800">Rate</p> <p class="mb-1.5 font-medium text-base dark:text-white text-coolGray-800">Rate</p>
<div class="relative"> <div class="relative">
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_rate_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g fill="#3b82f6">
<path d="M9,9h5L7,0,0,9H5V23a1,1,0,0,0,1,1H8a1,1,0,0,0,1-1Z" fill="#3b82f6"></path>
<path d="M14,17a3,3,0,1,1,3-3A3,3,0,0,1,14,17Zm0-4a1,1,0,1,0,1,1A1,1,0,0,0,14,13Z" data-color="color-2"></path>
<path d="M21,24a3,3,0,1,1,3-3A3,3,0,0,1,21,24Zm0-4a1,1,0,1,0,1,1A1,1,0,0,0,21,20Z" data-color="color-2"></path>
<path d="M13,23a1,1,0,0,1-.707-1.707l9-9a1,1,0,0,1,1.414,1.414l-9,9A1,1,0,0,1,13,23Z" data-color="color-2"></path>
</g>
</svg>
</div> </div>
<input class="pl-10 hover:border-blue-500 pl-10 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-white 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="rate" name="rate" value="{{ data.rate }}" onchange="set_rate('rate');"> <input class="pl-10 hover:border-blue-500 pl-10 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-white 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="rate" name="rate" value="{{ data.rate }}" onchange="set_rate('rate');">
</div> </div>
<div class="text-sm mt-2">
<a href="" id="get_rate_inferred_button" class="mt-2 dark:text-white bold text-coolGray-800">Get Rate Inferred:<span id="rate_inferred_display"></span></a>
</div>
<div class="flex form-check form-check-inline mt-5"> <div class="flex form-check form-check-inline mt-5">
<div class="flex items-center h-5"> <input class="form-check-input 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="rate_lock" name="rate_lock" value="rl" checked=checked> </div> <div class="flex items-center h-5">
<input class="form-check-input 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="rate_lock" name="rate_lock" value="rl" checked=checked>
</div>
<div class="ml-2 text-sm"> <div class="ml-2 text-sm">
<label class="form-check-label text-sm font-medium text-gray-800 dark:text-white" for="inlineCheckbox1">Lock Rate</label> <label class="form-check-label text-sm font-medium text-gray-800 dark:text-white" for="inlineCheckbox1">Lock Rate</label>
<p id="helper-checkbox-text" class="text-xs font-normal text-gray-500 dark:text-gray-300">Automatically adjusts the <b>You Get</b> value based on the rate youve entered. Without it, the rate value is automatically adjusted based on the number of coins you put in <b>You Get.</b></p> <p id="helper-checkbox-text" class="text-xs font-normal text-gray-500 dark:text-gray-300">Automatically adjusts the <b>You Get</b> value based on the rate youve entered. Without it, the rate value is automatically adjusted based on the number of coins you put in <b>You Get.</b></p>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="py-0 border-b items-center justify-between -mx-4 mb-6 pb-3 border-gray-400 border-opacity-20"> <div class="py-3 border-b items-center justify-between -mx-4 mb-6 pb-6 border-gray-400 border-opacity-20">
<div class="w-full md:w-10/12"> <div class="w-full md:w-10/12">
<div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0"> <div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0">
<div class="w-full md:w-1/3 p-6"> <div class="w-full md:w-1/3 p-3">
<p class="text-sm text-coolGray-800 dark:text-white font-semibold">Options</p> <p class="text-sm text-coolGray-800 dark:text-white font-semibold">Options</p>
</div> </div>
<div class="w-full md:flex-1 p-3"> <div class="w-full md:flex-1 p-3">
<div class="flex form-check form-check-inline">
<div class="flex items-center h-5"> <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="amt_var" name="amt_var" value="av" {% if data.amt_var==true %} checked="checked" {% endif %}> </div> <div class="flex form-check form-check-inline">
<div class="flex items-center h-5">
<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="amt_var" name="amt_var" value="av" {% if data.amt_var==true %} checked="checked" {% endif %}>
</div>
<div class="ml-2 text-sm"> <div class="ml-2 text-sm">
<label class="form-check-label text-sm font-medium text-gray-800 dark:text-white" for="inlineCheckbox2">Amount Variable</label> <label class="form-check-label text-sm font-medium text-gray-800 dark:text-white" for="inlineCheckbox2">Amount Variable</label>
<p id="helper-checkbox-text" class="text-xs font-normal text-gray-500 dark:text-gray-300">Allow bids with a different amount to the offer.</p> <p id="helper-checkbox-text" class="text-xs font-normal text-gray-500 dark:text-gray-300">Allow bids with a different amount to the offer.</p>
</div> </div>
</div>
<div class="flex mt-2 form-check form-check-inline">
<div class="flex items-center h-5">
<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="rate_var" name="rate_var" value="rv" {% if data.rate_var==true %} checked="checked" {% endif %}>
</div> </div>
<div class="flex mt-2 form-check form-check-inline">
<div class="flex items-center h-5"> <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="rate_var" name="rate_var" value="rv" {% if data.rate_var==true %} checked="checked" {% endif %}> </div>
<div class="ml-2 text-sm"> <div class="ml-2 text-sm">
<label class="form-check-label text-sm font-medium text-gray-800 dark:text-white" for="inlineCheckbox3">Rate Variable</label> <label class="form-check-label text-sm font-medium text-gray-800 dark:text-white" for="inlineCheckbox3">Rate Variable</label>
<p id="helper-checkbox-text" class="text-xs font-normal text-gray-500 dark:text-gray-300">Allow bids with a different rate to the offer.</p> <p id="helper-checkbox-text" class="text-xs font-normal text-gray-500 dark:text-gray-300">Allow bids with a different rate to the offer.</p>
</div> </div>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> <div class="pricejsonhidden hidden py-3 border-b items-center justify-between -mx-4 mb-6 pb-6 border-gray-400 border-opacity-20">
<div class="pricejsonhidden hidden py-3 border-b items-center justify-between -mx-4 mb-6 pb-3 border-gray-400 border-opacity-20">
<div class="w-full md:w-10/12"> <div class="w-full md:w-10/12">
<div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0"> <div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0">
<div class="w-full md:w-1/3 p-6"> <div class="w-full md:w-1/3 p-3">
<p class="text-sm text-coolGray-800 dark:text-white font-semibold">Coin Prices/Rates (JSON)</p> <p class="text-sm text-coolGray-800 dark:text-white font-semibold">Coin Prices/Rates (JSON)</p>
</div> </div>
<div class="w-full md:flex-1 p-3 dark:text-white text-sm monospace"> <div class="w-full md:flex-1 p-3 dark:text-white text-sm monospace">
@@ -284,11 +386,45 @@
</div> </div>
</div> </div>
</div> </div>
</div>
<div class="pricetablehidden hidden py-3 border-b items-center justify-between -mx-4 mb-6 pb-6 border-gray-400 border-opacity-20">
<div class="w-full md:w-10/12">
<div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0">
<div class="w-full md:w-1/3 p-3">
<p class="text-sm text-coolGray-800 dark:text-white font-semibold">Coin Prices/Rates (Table)</p>
</div>
<div class="w-full md:flex-1 p-3 dark:text-white text-sm">
<table id="priceTable" class="hidden w-full min-w-max 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">Coin</span>
</div>
</th>
<th class="p-0">
<div class="py-3 bg-coolGray-200 dark:bg-gray-600">
<span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">Price in USD</span>
</div>
</th>
<th class="p-0">
<div class="py-3 rounded-tr-xl bg-coolGray-200 dark:bg-gray-600">
<span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">Price in BTC (Rate)</span>
</div>
</th>
</tr>
</thead>
<tbody id="priceTableBody" class="text-gray-700">
</tbody>
</table>
</div> </div>
</div> </div>
</div> </div>
</section> </div>
<section> </div>
</div>
</section>
<section>
<div class="pl-6 pr-6 pt-0 pb-0 h-full overflow-hidden"> <div class="pl-6 pr-6 pt-0 pb-0 h-full overflow-hidden">
<div class="pb-6 border-coolGray-100"> <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 -m-2">
@@ -297,13 +433,26 @@
<div class="pt-6 pb-6 bg-coolGray-100 dark:bg-gray-500 rounded-xl"> <div class="pt-6 pb-6 bg-coolGray-100 dark:bg-gray-500 rounded-xl">
<div class="px-6"> <div class="px-6">
<div class="flex flex-wrap justify-end"> <div class="flex flex-wrap justify-end">
<!--<div class="w-full md:w-auto p-1.5"><button name="show_rates_table" type="button" value="Show Rates Table" onclick='lookup_rates_table();' class="flex flex-wrap justify-center w-full px-4 py-2.5 font-medium text-sm text-coolGray-500 hover:text-coolGray-600 border border-coolGray-200 hover:border-coolGray-300 bg-white rounded-md shadow-button focus:ring-0 focus:outline-none"><svg class="mr-2"
xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24"><g fill="#556987"><path fill="#556987" d="M12,3c1.989,0,3.873,0.65,5.43,1.833l-3.604,3.393l9.167,0.983L22.562,0l-3.655,3.442 C16.957,1.862,14.545,1,12,1C5.935,1,1,5.935,1,12h2C3,7.037,7.037,3,12,3z"></path><path data-color="#556987" d="M12,21c-1.989,0-3.873-0.65-5.43-1.833l3.604-3.393l-9.167-0.983L1.438,24l3.655-3.442 C7.043,22.138,9.455,23,12,23c6.065,0,11-4.935,11-11h-2C21,16.963,16.963,21,12,21z"></path></g></svg><span>Show Rates Table</span></button></div>-->
{% if show_chart %}
<div class="w-full md:w-auto p-1.5"> <div class="w-full md:w-auto p-1.5">
<button name="check_rates" type="button" value="Check Current Prices/Rates (JSON)" onclick='lookup_rates();' class="flex flex-wrap justify-center w-full px-4 py-2.5 font-medium text-sm text-coolGray-500 hover:text-coolGray-600 border border-coolGray-200 hover:border-coolGray-300 bg-white rounded-md focus:ring-0 focus:outline-none dark:text-white dark:hover:text-white dark:bg-gray-600 dark:hover:bg-gray-700 dark:border-gray-600 dark:hover:border-gray-600"> <button name="loadPrices" id="loadPricesButton" type="button" value="Check Current Prices/Rates (TABLE)" class="flex flex-wrap justify-center w-full px-4 py-2.5 font-medium text-sm text-coolGray-500 hover:text-coolGray-600 border border-coolGray-200 hover:border-coolGray-300 bg-white rounded-md focus:ring-0 focus:outline-none dark:text-white dark:hover:text-white dark:bg-gray-600 dark:hover:bg-gray-700 dark:border-gray-600 dark:hover:border-gray-600"><span>Check Current Prices/Rates (TABLE)</span>
<span>Check Current Prices/Rates (JSON)</span> </button>
</div>
{% endif %}
<div class="w-full md:w-auto p-1.5">
<button name="check_rates" type="button" value="Check Current Prices/Rates (JSON)" onclick='lookup_rates();' class="flex flex-wrap justify-center w-full px-4 py-2.5 font-medium text-sm text-coolGray-500 hover:text-coolGray-600 border border-coolGray-200 hover:border-coolGray-300 bg-white rounded-md focus:ring-0 focus:outline-none dark:text-white dark:hover:text-white dark:bg-gray-600 dark:hover:bg-gray-700 dark:border-gray-600 dark:hover:border-gray-600"><span>Check Current Prices/Rates (JSON)</span>
</button> </button>
</div> </div>
<div class="w-full md:w-auto p-1.5"> <div class="w-full md:w-auto p-1.5">
<button name="continue" value="Continue" 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"> <button name="continue" value="Continue" 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">
<svg class="mr-2" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
<circle cx="12" cy="12" r="11"></circle>
<polyline points="11 8 15 12 11 16" stroke="#ffffff"></polyline>
</g>
</svg>
<span>Continue</span> <span>Continue</span>
</button> </button>
</div> </div>
@@ -318,18 +467,25 @@
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<script>
const xhr_rates = new XMLHttpRequest(); <style>
xhr_rates.onload = () => { select.select-disabled {
opacity: 0.50 !important;
}
</style>
<script>
const xhr_rates = new XMLHttpRequest();
xhr_rates.onload = () => {
if (xhr_rates.status == 200) { if (xhr_rates.status == 200) {
const obj = JSON.parse(xhr_rates.response); const obj = JSON.parse(xhr_rates.response);
inner_html = '<pre><code>' + JSON.stringify(obj, null, ' ') + '</code></pre>'; inner_html = '<pre><code>' + JSON.stringify(obj, null, ' ') + '</code></pre>';
document.getElementById('rates_display').innerHTML = inner_html; document.getElementById('rates_display').innerHTML = inner_html;
} }
} }
const xhr_rate = new XMLHttpRequest(); const xhr_rate = new XMLHttpRequest();
xhr_rate.onload = () => { xhr_rate.onload = () => {
if (xhr_rate.status == 200) { if (xhr_rate.status == 200) {
const obj = JSON.parse(xhr_rate.response); const obj = JSON.parse(xhr_rate.response);
if (obj.hasOwnProperty('rate')) { if (obj.hasOwnProperty('rate')) {
@@ -342,9 +498,45 @@
document.getElementById('amt_from').value = obj['amount_from']; document.getElementById('amt_from').value = obj['amount_from'];
} }
} }
}
const xhr_rates_table = new XMLHttpRequest();
xhr_rates_table.onload = () => {
if (xhr_rates_table.status == 200) {
const list = JSON.parse(xhr_rates_table.response);
headings = ['Source', 'Coin From', 'Coin To', 'Coin From USD Rate', 'Coin To USD Rate', 'Coin From BTC Rate', 'Coin To BTC Rate', 'Relative Rate'];
table = document.createElement('table');
table.setAttribute("class", "");
heading_head = document.createElement('thead');
headings_row = document.createElement('tr');
data_row.setAttribute("class", "");
for (let i = 0; i < headings.length; i++) {
column = document.createElement('th');
column.textContent = headings[i];
headings_row.appendChild(column);
} }
table.appendChild(headings_row);
for (let i = 0; i < list.length; i++) {
data_row = document.createElement('tr');
for (let j = 0; j < list[i].length; j++) {
column = document.createElement('td');
column.textContent = list[i][j];
data_row.appendChild(column);
}
table.appendChild(data_row);
}
// Clear existing
const display_node = document.getElementById("rates_display");
while (display_node.lastElementChild) {
display_node.removeChild(display_node.lastElementChild);
}
heading = document.createElement('h4');
heading.textContent = ''
display_node.appendChild(heading);
display_node.appendChild(table);
}
}
function lookup_rates() { function lookup_rates() {
const coin_from = document.getElementById('coin_from').value; const coin_from = document.getElementById('coin_from').value;
const coin_to = document.getElementById('coin_to').value; const coin_to = document.getElementById('coin_to').value;
@@ -373,42 +565,27 @@
xhr_rates.open('POST', '/json/rates'); xhr_rates.open('POST', '/json/rates');
xhr_rates.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); xhr_rates.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr_rates.send('coin_from=' + selectedCoin + '&coin_to=' + coin_to); xhr_rates.send('coin_from=' + selectedCoin + '&coin_to=' + coin_to);
} }
function getRateInferred(event) {
event.preventDefault(); // Prevent default form submission behavior
function lookup_rates_table() {
const coin_from = document.getElementById('coin_from').value; const coin_from = document.getElementById('coin_from').value;
const coin_to = document.getElementById('coin_to').value; const coin_to = document.getElementById('coin_to').value;
const params = 'coin_from=' + encodeURIComponent(coin_from) + '&coin_to=' + encodeURIComponent(coin_to); if (coin_from == '-1' || coin_to == '-1') {
alert('Coins from and to must be set first.');
const xhr_rates = new XMLHttpRequest(); return;
xhr_rates.onreadystatechange = function() {
if (xhr_rates.readyState === XMLHttpRequest.DONE) {
//console.log(xhr_rates.responseText);
if (xhr_rates.status === 200) {
try {
const responseData = JSON.parse(xhr_rates.responseText);
const rateInferred = responseData.coingecko.rate_inferred;
//document.getElementById('rate_inferred_display').innerText = " (" + coin_from + " to " + coin_to + "): " + rateInferred;
document.getElementById('rate_inferred_display').innerText = " " + rateInferred;
} catch (error) {
console.error('Error parsing response:', error);
} }
} else { inner_html = 'Updating...</p>';
console.error('Error fetching data:', xhr_rates.statusText); document.getElementById('rates_display').innerHTML = inner_html;
}
}
};
xhr_rates.open('POST', '/json/rates'); // Remove the 'hidden' class
xhr_rates.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); document.querySelector(".hidden.py-3.border-b").classList.remove("hidden");
xhr_rates.send(params);
}
document.getElementById('get_rate_inferred_button').addEventListener('click', getRateInferred); xhr_rates_table.open('GET', '/json/rateslist?from=' + coin_from + '&to=' + coin_to);
xhr_rates_table.send();
}
function set_swap_type_enabled(coin_from, coin_to, swap_type) {
function set_swap_type_enabled(coin_from, coin_to, swap_type) {
const adaptor_sig_only_coins = ['6' /* XMR */, '8' /* PART_ANON */, '7' /* PART_BLIND */, '13' /* FIRO */]; const adaptor_sig_only_coins = ['6' /* XMR */, '8' /* PART_ANON */, '7' /* PART_BLIND */, '13' /* FIRO */];
const secret_hash_only_coins = ['11' /* PIVX */, '12' /* DASH */]; const secret_hash_only_coins = ['11' /* PIVX */, '12' /* DASH */];
let make_hidden = false; let make_hidden = false;
@@ -416,16 +593,16 @@
swap_type.disabled = true; swap_type.disabled = true;
swap_type.value = 'xmr_swap'; swap_type.value = 'xmr_swap';
make_hidden = true; make_hidden = true;
swap_type.classList.add('select-disabled'); swap_type.classList.add('select-disabled'); // Add the class to the disabled select
} else } else
if (secret_hash_only_coins.includes(coin_from) && secret_hash_only_coins.includes(coin_to)) { if (secret_hash_only_coins.includes(coin_from) && secret_hash_only_coins.includes(coin_to)) {
swap_type.disabled = true; swap_type.disabled = true;
swap_type.value = 'seller_first'; swap_type.value = 'seller_first';
make_hidden = true; make_hidden = true;
swap_type.classList.add('select-disabled'); swap_type.classList.add('select-disabled'); // Add the class to the disabled select
} else { } else {
swap_type.disabled = false; swap_type.disabled = false;
swap_type.classList.remove('select-disabled'); swap_type.classList.remove('select-disabled'); // Remove the class from the enabled select
} }
let swap_type_hidden = document.getElementById('swap_type_hidden'); let swap_type_hidden = document.getElementById('swap_type_hidden');
if (make_hidden) { if (make_hidden) {
@@ -441,9 +618,9 @@
if (swap_type_hidden) { if (swap_type_hidden) {
swap_type_hidden.parentNode.removeChild(swap_type_hidden); swap_type_hidden.parentNode.removeChild(swap_type_hidden);
} }
} }
function set_rate(value_changed) { function set_rate(value_changed) {
const coin_from = document.getElementById('coin_from').value; const coin_from = document.getElementById('coin_from').value;
const coin_to = document.getElementById('coin_to').value; const coin_to = document.getElementById('coin_to').value;
const amt_from = document.getElementById('amt_from').value; const amt_from = document.getElementById('amt_from').value;
@@ -459,17 +636,10 @@
} }
params = 'coin_from=' + coin_from + '&coin_to=' + coin_to; params = 'coin_from=' + coin_from + '&coin_to=' + coin_to;
if (value_changed == 'rate' || (lock_rate && value_changed == 'amt_from') || (amt_to == '' && value_changed == 'amt_from')) { if (value_changed == 'rate' || (lock_rate && value_changed == 'amt_from') || (amt_to == '' && value_changed == 'amt_from')) {
if (rate == '' || (amt_from == '' && amt_to == '')) { if (amt_from == '' || rate == '') {
return;
} else
if (amt_from == '' && amt_to != '') {
if (value_changed == 'amt_from') { // Don't try and set a value just cleared
return; return;
} }
params += '&rate=' + rate + '&amt_to=' + amt_to;
} else {
params += '&rate=' + rate + '&amt_from=' + amt_from; params += '&rate=' + rate + '&amt_from=' + amt_from;
}
} else } else
if (lock_rate && value_changed == 'amt_to') { if (lock_rate && value_changed == 'amt_to') {
if (amt_to == '' || rate == '') { if (amt_to == '' || rate == '') {
@@ -485,17 +655,73 @@
xhr_rate.open('POST', '/json/rate'); xhr_rate.open('POST', '/json/rate');
xhr_rate.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); xhr_rate.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr_rate.send(params); xhr_rate.send(params);
} }
document.addEventListener("DOMContentLoaded", function() { document.addEventListener("DOMContentLoaded", function() {
const coin_from = document.getElementById('coin_from').value; const coin_from = document.getElementById('coin_from').value;
const coin_to = document.getElementById('coin_to').value; const coin_to = document.getElementById('coin_to').value;
const swap_type = document.getElementById('swap_type'); const swap_type = document.getElementById('swap_type');
set_swap_type_enabled(coin_from, coin_to, swap_type); set_swap_type_enabled(coin_from, coin_to, swap_type);
});
{% if show_chart %}
document.addEventListener('DOMContentLoaded', function() {
const loadPricesButton = document.getElementById("loadPricesButton");
function loadPrices() {
const api_key = '{{chart_api_key}}';
const coins = ['BTC', 'PART', 'XMR', 'LTC', 'FIRO', 'DASH', 'PIVX', 'DOGE'];
document.getElementById("priceTable").classList.remove("hidden");
coins.forEach(coin => {
fetch(`https://min-api.cryptocompare.com/data/pricemultifull?fsyms=${coin}&tsyms=USD,BTC&api_key=${api_key}`)
.then(response => response.json())
.then(data => {
const priceUSD = data.RAW[coin].USD.PRICE;
const priceBTC = data.RAW[coin].BTC.PRICE;
const tableRow = document.createElement("tr");
tableRow.classList.add("opacity-100", "text-gray-500", "dark:text-gray-100",
"dark:text-gray-100", "hover:bg-coolGray-200",
"dark:hover:bg-gray-600");
const coinCell = document.createElement("td");
coinCell.textContent = coin;
coinCell.classList.add("py-3", "px-6", "bold");
tableRow.appendChild(coinCell);
const usdPriceCell = document.createElement("td");
usdPriceCell.textContent = priceUSD.toFixed(2) + ' USD';
usdPriceCell.classList.add("py-3");
tableRow.appendChild(usdPriceCell);
const btcPriceCell = document.createElement("td");
btcPriceCell.classList.add("py-3");
if (coin !== 'BTC') {
btcPriceCell.textContent = priceBTC.toFixed(8) + ' BTC';
} else {
btcPriceCell.textContent = '-';
}
tableRow.appendChild(btcPriceCell);
document.getElementById("priceTableBody").appendChild(tableRow);
})
.catch(error => console.error(`Error fetching ${coin} data:`, error));
}); });
</script>
</div> document.querySelector(".pricetablehidden").classList.remove("hidden");
loadPricesButton.disabled = true;
}
loadPricesButton.addEventListener("click", loadPrices);
});
{% endif %}
</script>
<script src="static/js/new_offer.js"></script> <script src="static/js/new_offer.js"></script>
<script src="static/js/coin_icons.js"></script>
<script src="static/js/coin_icons_2.js"></script>
</div>
{% include 'footer.html' %} {% include 'footer.html' %}
</div> </div>
</body> </body>

View File

@@ -1,23 +1,35 @@
{% include 'header.html' %} {% from 'style.html' import breadcrumb_line_svg, input_down_arrow_offer_svg, select_network_svg, select_address_svg, select_swap_type_svg, select_bid_amount_svg, select_rate_svg, step_one_svg, step_two_svg, step_three_svg, select_setup_svg, input_time_svg, select_target_svg , select_auto_strategy_svg %} {% include 'header.html' %}
<script src="static/js/coin_icons.js"></script>
<div class="container mx-auto"> <div class="container mx-auto">
<section class="p-5 mt-5"> <section class="p-5 mt-5">
<div class="flex flex-wrap items-center -m-2"> <div class="flex flex-wrap items-center -m-2">
<div class="w-full md:w-1/2 p-2"> <div class="w-full md:w-1/2 p-2">
<ul class="flex flex-wrap items-center gap-x-3 mb-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="/"> <li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/">
<p>Home</p> <p>Home</p>
</a> </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="/newoffer">Placer</a> <svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</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="#">Setup</a> <a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/newoffer">Place an new offer</a>
</li>
<li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
<li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="#">Setup offers parameters</a>
</li>
<li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li> </li>
{{ breadcrumb_line_svg | safe }}
</ul> </ul>
</div> </div>
</div> </div>
@@ -30,8 +42,8 @@
<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=""> <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="">
<div class="relative z-20 flex flex-wrap items-center -m-3"> <div class="relative z-20 flex flex-wrap items-center -m-3">
<div class="w-full md:w-1/2 p-3"> <div class="w-full md:w-1/2 p-3">
<h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">Setup Offers Parameters</h2> <h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">Setup offers parameters</h2>
<p class="font-normal text-coolGray-200 dark:text-white">Place an order on the network order book.</p> <p class="font-normal text-coolGray-200 dark:text-white">Place an order on the order book.</p>
</div> </div>
</div> </div>
</div> </div>
@@ -39,31 +51,38 @@
</section> </section>
{% include 'inc_messages.html' %} {% include 'inc_messages.html' %}
<section> <section>
<div class="p-5 mb-5"> <div class="p-5 mb-10">
<div class="mx-4 p-4"> <div class="mx-4 p-4">
<div class="flex items-center"> <div class="flex items-center">
<div class="flex items-center text-teal-600 relative"> <div class="flex items-center text-teal-600 relative">
<div class="rounded-full h-12 w-12 py-3 border-2 border-blue-500"> <div class="rounded-full h-12 w-12 py-3 border-2 border-blue-500">
{{ step_one_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 24 24">
<g fill="#3b82f6">
<polygon points="14.5 23.5 11.5 23.5 11.5 4.321 6.766 8.108 4.892 5.766 11.474 0.5 14.5 0.5 14.5 23.5" fill="#3b82f6"></polygon>
</g>
</svg>
</div> </div>
<div class="absolute top-0 -ml-10 text-center mt-16 w-32 text-xs font-medium uppercase dark:text-white text-gray-600">Step 1</div> <div class="absolute top-0 -ml-10 text-center mt-16 w-32 text-xs font-medium uppercase dark:text-white text-gray-600">Step 1</div>
</div> </div>
<div class="flex-auto border-t-2 border-blue-500 dark:border-blue-500"></div> <div class="flex-auto border-t-2 border-blue-500 dark:border-blue-500"></div>
<div class="flex items-center text-teal-600 relative "> <div class="flex items-center text-teal-600 relative ">
<div class="rounded-full transition duration-500 ease-in-out h-12 w-12 py-3 border-2 border-blue-500 dark:border-blue-500"> <div class="rounded-full transition duration-500 ease-in-out h-12 w-12 py-3 border-2 border-blue-500 dark:border-blue-500">
{{ step_two_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 24 24">
<g fill="#3b82f6">
<path d="M19.5,23.5H4.5V20.2l.667-.445C9.549,16.828,16.5,10.78,16.5,7c0-2.654-1.682-4-5-4A9.108,9.108,0,0,0,7.333,4.248L6.084,5.08,4.42,2.584l1.247-.832A11.963,11.963,0,0,1,11.5,0c4.935,0,8,2.683,8,7,0,5-6.5,10.662-10.232,13.5H19.5ZM6,21H6Z" fill="#3b82f6"></path>
</g>
</svg>
</div> </div>
<div class="absolute top-0 -ml-10 text-center mt-16 w-32 text-xs font-medium uppercase dark:text-white text-gray-600">Step 2</div> <div class="absolute top-0 -ml-10 text-center mt-16 w-32 text-xs font-medium uppercase dark:text-white text-gray-600">Step 2</div>
</div> </div>
<div class="flex-auto border-t-2 border-teal-600 dark:border-gray-400"></div>
<div class="flex-auto border-t-2 border-gray-300 dark:border-gray-400"></div>
<div class="flex items-center text-gray-500 relative"> <div class="flex items-center text-gray-500 relative">
<div class="rounded-full transition duration-500 ease-in-out h-12 w-12 py-3 border-2 border-gray-300 dark:border-gray-400"> <div class="rounded-full transition duration-500 ease-in-out h-12 w-12 py-3 border-2 border-teal-600 dark:border-gray-400">
{{ step_three_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 24 24">
<g fill="#3b82f6">
<polygon points="9 21 1 13 4 10 9 15 21 3 24 6 9 21" fill="#d1d5db"></polygon>
</g>
</svg>
</div> </div>
<div class="absolute top-0 -ml-10 text-center mt-16 w-32 text-xs font-medium uppercase dark:text-white text-gray-600">Confirm</div> <div class="absolute top-0 -ml-10 text-center mt-16 w-32 text-xs font-medium uppercase dark:text-white text-gray-600">Confirm</div>
</div> </div>
@@ -74,21 +93,36 @@
<section class="py-3"> <section class="py-3">
<div class="container px-4 mx-auto"> <div class="container px-4 mx-auto">
<div class="p-8 bg-coolGray-100 dark:bg-gray-500 rounded-xl"> <div class="p-8 bg-coolGray-100 dark:bg-gray-500 rounded-xl">
<div class="flex flex-wrap items-center justify-between -mx-4 pb-6 border-gray-400 border-opacity-20"> </div> <div class="flex flex-wrap items-center justify-between -mx-4 mb-8 pb-6 border-b border-gray-400 border-opacity-20">
<div class="w-full sm:w-auto px-4 mb-6 sm:mb-0">
<h4 class="text-2xl font-bold tracking-wide dark:text-white mb-1">STEP 2</h4>
<!-- todo add subtitle <p class="text-sm text-coolGray-500">Lorem ipsum dolor sit amet</p> -->
</div>
</div>
<form method="post" autocomplete="off" id='form'> <form method="post" autocomplete="off" id='form'>
<div class="py-3 border-b items-center justify-between -mx-4 mb-6 pb-3 border-gray-400 border-opacity-20"> <div class="py-3 border-b items-center justify-between -mx-4 mb-6 pb-6 border-gray-400 border-opacity-20">
<div class="w-full md:w-10/12"> <div class="w-full md:w-10/12">
<div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0"> <div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0">
<div class="w-full md:w-1/3 p-6"> <div class="w-full md:w-1/3 p-3">
<p class="text-sm text-coolGray-800 dark:text-white font-semibold">Select Network</p> <p class="text-sm text-coolGray-800 dark:text-white font-semibold">Select Network</p>
</div> </div>
<div class="w-full md:flex-1 p-3"> <div class="w-full md:flex-1 p-3">
<div class="relative"> <div class="relative">
{{ input_down_arrow_offer_svg | safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_network_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<line data-cap="butt" x1="7.6" y1="10.5" x2="16.4" y2="5.5" stroke="#3b82f6"></line>
<line data-cap="butt" x1="7.6" y1="13.5" x2="16.4" y2="18.5" stroke="#3b82f6"></line>
<circle cx="5" cy="12" r="3"></circle>
<circle cx="19" cy="4" r="3"></circle>
<circle cx="19" cy="20" r="3"></circle>
</g>
</svg>
</div> </div>
<select class="cursor-not-allowed disabled-select hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="addr_to" disabled> <select class="cursor-not-allowed disabled-select pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0 disabled:opacity-20" name="addr_to" disabled>
<option{% if data.addr_to=="-1" %} selected{% endif %} value="-1">Public Network</option> <option{% if data.addr_to=="-1" %} selected{% endif %} value="-1">Public Network</option>
{% for a in addrs_to %} {% for a in addrs_to %}
<option{% if data.addr_to==a[0] %} selected{% endif %} value="{{ a[0] }}">{{ a[0] }} {{ a[1] }}</option> <option{% if data.addr_to==a[0] %} selected{% endif %} value="{{ a[0] }}">{{ a[0] }} {{ a[1] }}</option>
@@ -99,19 +133,28 @@
</div> </div>
</div> </div>
</div> </div>
<div class="py-0 border-b items-center justify-between -mx-4 mb-6 pb-3 border-gray-400 border-opacity-20"> <div class="py-3 border-b items-center justify-between -mx-4 mb-6 pb-6 border-gray-400 border-opacity-20">
<div class="w-full md:w-10/12"> <div class="w-full md:w-10/12">
<div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0"> <div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0">
<div class="w-full md:w-1/3 p-6"> <div class="w-full md:w-1/3 p-3">
<p class="text-sm text-coolGray-800 dark:text-white font-semibold">Select Address</p> <p class="text-sm text-coolGray-800 dark:text-white font-semibold">Select Address</p>
</div> </div>
<div class="w-full md:flex-1 p-3"> <div class="w-full md:flex-1 p-3">
<div class="relative"> <div class="relative">
{{ input_down_arrow_offer_svg | safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_address_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path data-cap="butt" d="M11.992,11.737,14.2,13.4A2,2,0,0,1,15,15v1H7V15a2,2,0,0,1,.8-1.6l2.208-1.663" stroke="#3b82f6"></path>
<rect x="9" y="7" width="4" height="5" rx="2" ry="2" stroke="#3b82f6"></rect>
<path d="M2,1H18a2,2,0,0,1,2,2V21a2,2,0,0,1-2,2H2Z"></path>
<line x1="23" y1="5" x2="23" y2="9" stroke="#3b82f6"></line>
</g>
</svg>
</div> </div>
<select class="cursor-not-allowed disabled-select hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="addr_from" disabled> <select class="cursor-not-allowed disabled-select pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="addr_from" disabled>
{% for a in addrs %} {% for a in addrs %}
<option{% if data.addr_from==a[0] %} selected{% endif %} value="{{ a[0] }}">{{ a[0] }} {{ a[1] }}</option> <option{% if data.addr_from==a[0] %} selected{% endif %} value="{{ a[0] }}">{{ a[0] }} {{ a[1] }}</option>
{% endfor %} {% endfor %}
@@ -122,17 +165,26 @@
</div> </div>
</div> </div>
</div> </div>
<div class="py-0 border-b items-center justify-between -mx-4 mb-6 pb-3 border-gray-400 border-opacity-20"> <div class="py-3 border-b items-center justify-between -mx-4 mb-6 pb-6 border-gray-400 border-opacity-20">
<div class="w-full md:w-10/12"> <div class="w-full md:w-10/12">
<div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0"> <div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0">
<div class="w-full md:w-1/3 p-6"> <div class="w-full md:w-1/3 p-3">
<p class="text-sm text-coolGray-800 dark:text-white font-semibold">Swap Type</p> <p class="text-sm text-coolGray-800 dark:text-white font-semibold">Swap Type</p>
</div> </div>
<div class="w-full md:flex-1 p-3"> <div class="w-full md:flex-1 p-3">
<div class="relative"> <div class="relative">
{{ input_down_arrow_offer_svg | safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_swap_type_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path data-cap="butt" d="M11.992,11.737,14.2,13.4A2,2,0,0,1,15,15v1H7V15a2,2,0,0,1,.8-1.6l2.208-1.663" stroke="#3b82f6"></path>
<rect x="9" y="7" width="4" height="5" rx="2" ry="2" stroke="#3b82f6"></rect>
<path d="M2,1H18a2,2,0,0,1,2,2V21a2,2,0,0,1-2,2H2Z"></path>
<line x1="23" y1="5" x2="23" y2="9" stroke="#3b82f6"></line>
</g>
</svg>
</div> </div>
<select class="cursor-not-allowed disabled-select pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="swap_type" id="swap_type" disabled> <select class="cursor-not-allowed disabled-select pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="swap_type" id="swap_type" disabled>
{% for a in swap_types %} {% for a in swap_types %}
@@ -144,34 +196,47 @@
</div> </div>
</div> </div>
</div> </div>
<div class="py-0 border-b items-center justify-between -mx-4 mb-6 pb-3 border-gray-400 border-opacity-20"> <div class="py-3 border-b items-center justify-between -mx-4 mb-6 pb-6 border-gray-400 border-opacity-20">
<div class="w-full md:w-10/12"> <div class="w-full md:w-10/12">
<div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0"> <div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0">
<div class="w-full md:w-1/3 p-6"> <div class="w-full md:w-1/3 p-3">
<p class="text-sm text-coolGray-800 dark:text-white font-semibold">You Send</p> <p class="text-sm text-coolGray-800 dark:text-white font-semibold">You Send</p>
</div> </div>
<div class="w-full md:flex-1 p-3"> <div class="w-full md:flex-1 p-3">
<div class="flex flex-wrap -m-3"> <div class="flex flex-wrap -m-3">
<div class="w-full md:w-1/2 p-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">Coin You Send</p>
<div class="custom-select"> <div class="custom-select">
<div class="relative"> <div class="relative">
{{ input_down_arrow_offer_svg | safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<select class="select cursor-not-allowed disabled-select hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-5 focus:ring-0" id="coin_from" name="coin_from" disabled> <path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<select class="select cursor-not-allowed disabled-select hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" id="coin_from" name="coin_from" onchange="set_rate('coin_from');" disabled>
<option value="-1">Select coin you send</option> <option value="-1">Select coin you send</option>
{% for c in coins_from %} {% for c in coins_from %}
<option{% if data.coin_from==c[0] %} selected{% endif %} value="{{ c[0] }}" data-image="/static/images/coins/{{ c[1]|replace(" ", "-") }}-20.png">{{ c[1] }}</option> <option{% if data.coin_from==c[0] %} selected{% endif %} value="{{ c[0] }}" data-image="/static/images/coins/{{ c[1]|replace(" ", "-") }}-20.png">{{ c[1] }}</option>
{% endfor %} {% endfor %}
</select> </select>
<div class="select-dropdown"> <div class="select-dropdown">
<img class="select-icon" src="" alt=""> <img class="select-image" src="" alt=""></div> <img class="select-icon" src="" alt="">
<img class="select-image" src="" alt="">
</div>
</div> </div>
</div> </div>
</div> </div>
<div class="w-full md:w-1/2 p-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">Amount You Send</p>
<div class="relative"> <div class="relative">
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> </div> <input class="cursor-not-allowed disabled-input appearance-none pr-10 bg-gray-50 text-gray-900 appearance-none dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-5 focus:ring-0" type="text" id="amt_from" name="amt_from" value="{{ data.amt_from }}" readonly> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path d="M15.6,13.873a2.273,2.273,0,0,1-.825,1.833,4.1,4.1,0,0,1-2.31.829v1.47h-.982V16.563a7.95,7.95,0,0,1-3.07-.617V14.053a8.328,8.328,0,0,0,1.5.545,8.019,8.019,0,0,0,1.568.28V12.654L11,12.468a5.357,5.357,0,0,1-2.012-1.216A2.332,2.332,0,0,1,8.4,9.627a2.123,2.123,0,0,1,.814-1.71,4.143,4.143,0,0,1,2.27-.812v-1.1h.982V7.074a8.126,8.126,0,0,1,2.97.66l-.674,1.678a7.768,7.768,0,0,0-2.3-.559v2.116a11.073,11.073,0,0,1,1.991.932,2.733,2.733,0,0,1,.867.868A2.146,2.146,0,0,1,15.6,13.873ZM10.558,9.627a.678.678,0,0,0,.219.52,2.569,2.569,0,0,0,.707.42V8.881Q10.559,9.017,10.558,9.627Zm2.884,4.354a.646.646,0,0,0-.244-.509,3.173,3.173,0,0,0-.732-.431v1.786Q13.441,14.662,13.442,13.981Z" stroke="none" fill="#3b82f6"></path>
<polyline points="5.346 7.929 6.932 2.237 1.135 2.966"></polyline>
<path data-cap="butt" d="M11.789,23A11,11,0,0,1,6.932,2.237"></path>
<polyline points="18.654 16.071 17.068 21.763 22.865 21.034"></polyline>
<path data-cap="butt" d="M12.211,1a11,11,0,0,1,4.857,20.763"></path>
</g>
</svg>
</div>
<input class="cursor-not-allowed disabled-input appearance-none pl-10 pl-10 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-white 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="amt_from" name="amt_from" value="{{ data.amt_from }}" onchange="set_rate('amt_from');" readonly>
</div> </div>
</div> </div>
{% if data.swap_style == 'xmr' %} {% if data.swap_style == 'xmr' %}
@@ -179,7 +244,15 @@
<p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Fee From Confirm Target</p> <p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Fee From Confirm Target</p>
<div class="relative"> <div class="relative">
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_target_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path d="M15.6,13.873a2.273,2.273,0,0,1-.825,1.833,4.1,4.1,0,0,1-2.31.829v1.47h-.982V16.563a7.95,7.95,0,0,1-3.07-.617V14.053a8.328,8.328,0,0,0,1.5.545,8.019,8.019,0,0,0,1.568.28V12.654L11,12.468a5.357,5.357,0,0,1-2.012-1.216A2.332,2.332,0,0,1,8.4,9.627a2.123,2.123,0,0,1,.814-1.71,4.143,4.143,0,0,1,2.27-.812v-1.1h.982V7.074a8.126,8.126,0,0,1,2.97.66l-.674,1.678a7.768,7.768,0,0,0-2.3-.559v2.116a11.073,11.073,0,0,1,1.991.932,2.733,2.733,0,0,1,.867.868A2.146,2.146,0,0,1,15.6,13.873ZM10.558,9.627a.678.678,0,0,0,.219.52,2.569,2.569,0,0,0,.707.42V8.881Q10.559,9.017,10.558,9.627Zm2.884,4.354a.646.646,0,0,0-.244-.509,3.173,3.173,0,0,0-.732-.431v1.786Q13.441,14.662,13.442,13.981Z" stroke="none" fill="#3b82f6"></path>
<polyline points="5.346 7.929 6.932 2.237 1.135 2.966"></polyline>
<path data-cap="butt" d="M11.789,23A11,11,0,0,1,6.932,2.237"></path>
<polyline points="18.654 16.071 17.068 21.763 22.865 21.034"></polyline>
<path data-cap="butt" d="M12.211,1a11,11,0,0,1,4.857,20.763"></path>
</g>
</svg>
</div> </div>
<input class="pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" type="number" name="fee_from_conf" min="1" max="32" value="{{ data.fee_from_conf }}"> <input class="pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" type="number" name="fee_from_conf" min="1" max="32" value="{{ data.fee_from_conf }}">
</div> </div>
@@ -187,10 +260,21 @@
<div class="w-full md:w-1/2 p-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">Fee From Increase By</p> <p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Fee From Increase By</p>
<div class="relative"> <div class="relative">
{{ input_down_arrow_offer_svg | safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_rate_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
</div> <select class="pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="fee_from_extra"> <g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path d="M15.6,13.873a2.273,2.273,0,0,1-.825,1.833,4.1,4.1,0,0,1-2.31.829v1.47h-.982V16.563a7.95,7.95,0,0,1-3.07-.617V14.053a8.328,8.328,0,0,0,1.5.545,8.019,8.019,0,0,0,1.568.28V12.654L11,12.468a5.357,5.357,0,0,1-2.012-1.216A2.332,2.332,0,0,1,8.4,9.627a2.123,2.123,0,0,1,.814-1.71,4.143,4.143,0,0,1,2.27-.812v-1.1h.982V7.074a8.126,8.126,0,0,1,2.97.66l-.674,1.678a7.768,7.768,0,0,0-2.3-.559v2.116a11.073,11.073,0,0,1,1.991.932,2.733,2.733,0,0,1,.867.868A2.146,2.146,0,0,1,15.6,13.873ZM10.558,9.627a.678.678,0,0,0,.219.52,2.569,2.569,0,0,0,.707.42V8.881Q10.559,9.017,10.558,9.627Zm2.884,4.354a.646.646,0,0,0-.244-.509,3.173,3.173,0,0,0-.732-.431v1.786Q13.441,14.662,13.442,13.981Z" stroke="none" fill="#3b82f6"></path>
<polyline points="5.346 7.929 6.932 2.237 1.135 2.966"></polyline>
<path data-cap="butt" d="M11.789,23A11,11,0,0,1,6.932,2.237"></path>
<polyline points="18.654 16.071 17.068 21.763 22.865 21.034"></polyline>
<path data-cap="butt" d="M12.211,1a11,11,0,0,1,4.857,20.763"></path>
</g>
</svg>
</div>
<select class="pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="fee_from_extra">
<option value="0">None</option> <option value="0">None</option>
<option value="10" {% if data.fee_from_extra==10 %} selected{% endif %}>10%</option> <option value="10" {% if data.fee_from_extra==10 %} selected{% endif %}>10%</option>
<option value="50" {% if data.fee_from_extra==50 %} selected{% endif %}>50%</option> <option value="50" {% if data.fee_from_extra==50 %} selected{% endif %}>50%</option>
@@ -204,57 +288,89 @@
</div> </div>
</div> </div>
</div> </div>
<div class="py-0 border-b items-center justify-between -mx-4 mb-6 pb-3 border-gray-400 border-opacity-20"> <div class="py-3 border-b items-center justify-between -mx-4 mb-6 pb-6 border-gray-400 border-opacity-20">
<div class="w-full md:w-10/12"> <div class="w-full md:w-10/12">
<div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0"> <div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0">
<div class="w-full md:w-1/3 p-6"> <div class="w-full md:w-1/3 p-3">
<p class="text-sm text-coolGray-800 dark:text-white font-semibold">You Get</p> <p class="text-sm text-coolGray-800 dark:text-white font-semibold">You Get</p>
</div> </div>
<div class="w-full md:flex-1 p-3"> <div class="w-full md:flex-1 p-3">
<div class="flex flex-wrap -m-3"> <div class="flex flex-wrap -m-3">
<div class="w-full md:w-1/2 p-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">Coin You Get</p>
<div class="custom-select"> <div class="custom-select">
<div class="relative"> <div class="relative">
{{ input_down_arrow_offer_svg | safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<select class="select cursor-not-allowed disabled-select hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-5 focus:ring-0" id="coin_to" name="coin_to" disabled> <path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<select class="select cursor-not-allowed disabled-select hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" id="coin_to" name="coin_to" onchange="set_rate('coin_to');" disabled>
<option value="-1"></option> <option value="-1"></option>
{% for c in coins %} {% for c in coins %}
<option{% if data.coin_to==c[0] %} selected{% endif %} value="{{ c[0] }}" data-image="/static/images/coins/{{ c[1]|replace(" ", "-") }}-20.png">{{ c[1] }}</option> <option{% if data.coin_to==c[0] %} selected{% endif %} value="{{ c[0] }}" data-image="/static/images/coins/{{ c[1]|replace(" ", "-") }}-20.png">{{ c[1] }}</option>
{% endfor %} {% endfor %}
</select> </select>
<div class="select-dropdown"> <img class="select-icon" src="" alt=""> <img class="select-image" src="" alt=""> </div> <div class="select-dropdown">
<img class="select-icon" src="" alt="">
<img class="select-image" src="" alt="">
</div>
</div> </div>
</div> </div>
</div> </div>
<div class="w-full md:w-1/2 p-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">Amount You Get</p>
<div class="relative"> <div class="relative">
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> </div> <input class="cursor-not-allowed disabled-input hover:border-blue-500 pr-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-5 focus:ring-0" type="text" id="amt_to" name="amt_to" value="{{ data.amt_to }}" readonly> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path d="M15.6,13.873a2.273,2.273,0,0,1-.825,1.833,4.1,4.1,0,0,1-2.31.829v1.47h-.982V16.563a7.95,7.95,0,0,1-3.07-.617V14.053a8.328,8.328,0,0,0,1.5.545,8.019,8.019,0,0,0,1.568.28V12.654L11,12.468a5.357,5.357,0,0,1-2.012-1.216A2.332,2.332,0,0,1,8.4,9.627a2.123,2.123,0,0,1,.814-1.71,4.143,4.143,0,0,1,2.27-.812v-1.1h.982V7.074a8.126,8.126,0,0,1,2.97.66l-.674,1.678a7.768,7.768,0,0,0-2.3-.559v2.116a11.073,11.073,0,0,1,1.991.932,2.733,2.733,0,0,1,.867.868A2.146,2.146,0,0,1,15.6,13.873ZM10.558,9.627a.678.678,0,0,0,.219.52,2.569,2.569,0,0,0,.707.42V8.881Q10.559,9.017,10.558,9.627Zm2.884,4.354a.646.646,0,0,0-.244-.509,3.173,3.173,0,0,0-.732-.431v1.786Q13.441,14.662,13.442,13.981Z" stroke="none" fill="#3b82f6"></path>
<polyline points="5.346 7.929 6.932 2.237 1.135 2.966"></polyline>
<path data-cap="butt" d="M11.789,23A11,11,0,0,1,6.932,2.237"></path>
<polyline points="18.654 16.071 17.068 21.763 22.865 21.034"></polyline>
<path data-cap="butt" d="M12.211,1a11,11,0,0,1,4.857,20.763"></path>
</g>
</svg>
</div>
<input class="cursor-not-allowed disabled-input pl-10 hover:border-blue-500 pl-10 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-white 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="amt_to" name="amt_to" value="{{ data.amt_to }}" onchange="set_rate('amt_to');" readonly>
</div> </div>
</div> </div>
{% if data.swap_style == 'xmr' and coin_to != '6' %} {% if data.swap_style == 'xmr' and coin_to != '6' %}
<div class="w-full md:w-1/2 p-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">Fee To Confirm Target</p> <p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Fee From Confirm Target</p>
<div class="relative"> <div class="relative">
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_target_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path d="M15.6,13.873a2.273,2.273,0,0,1-.825,1.833,4.1,4.1,0,0,1-2.31.829v1.47h-.982V16.563a7.95,7.95,0,0,1-3.07-.617V14.053a8.328,8.328,0,0,0,1.5.545,8.019,8.019,0,0,0,1.568.28V12.654L11,12.468a5.357,5.357,0,0,1-2.012-1.216A2.332,2.332,0,0,1,8.4,9.627a2.123,2.123,0,0,1,.814-1.71,4.143,4.143,0,0,1,2.27-.812v-1.1h.982V7.074a8.126,8.126,0,0,1,2.97.66l-.674,1.678a7.768,7.768,0,0,0-2.3-.559v2.116a11.073,11.073,0,0,1,1.991.932,2.733,2.733,0,0,1,.867.868A2.146,2.146,0,0,1,15.6,13.873ZM10.558,9.627a.678.678,0,0,0,.219.52,2.569,2.569,0,0,0,.707.42V8.881Q10.559,9.017,10.558,9.627Zm2.884,4.354a.646.646,0,0,0-.244-.509,3.173,3.173,0,0,0-.732-.431v1.786Q13.441,14.662,13.442,13.981Z" stroke="none" fill="#3b82f6"></path>
<polyline points="5.346 7.929 6.932 2.237 1.135 2.966"></polyline>
<path data-cap="butt" d="M11.789,23A11,11,0,0,1,6.932,2.237"></path>
<polyline points="18.654 16.071 17.068 21.763 22.865 21.034"></polyline>
<path data-cap="butt" d="M12.211,1a11,11,0,0,1,4.857,20.763"></path>
</g>
</svg>
</div> </div>
<input class="disabled-input pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" type="number" name="fee_to_conf" min="1" max="32" value="{{ data.fee_to_conf }}"> <input class="disabled-input pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" type="number" name="fee_to_conf" min="1" max="32" value="{{ data.fee_from_conf }}">
</div> </div>
</div> </div>
<div class="w-full md:w-1/2 p-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">Fee To Increase By</p> <p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Fee From Increase By</p>
<div class="relative"> <div class="relative">
{{ input_down_arrow_offer_svg | safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_rate_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path d="M15.6,13.873a2.273,2.273,0,0,1-.825,1.833,4.1,4.1,0,0,1-2.31.829v1.47h-.982V16.563a7.95,7.95,0,0,1-3.07-.617V14.053a8.328,8.328,0,0,0,1.5.545,8.019,8.019,0,0,0,1.568.28V12.654L11,12.468a5.357,5.357,0,0,1-2.012-1.216A2.332,2.332,0,0,1,8.4,9.627a2.123,2.123,0,0,1,.814-1.71,4.143,4.143,0,0,1,2.27-.812v-1.1h.982V7.074a8.126,8.126,0,0,1,2.97.66l-.674,1.678a7.768,7.768,0,0,0-2.3-.559v2.116a11.073,11.073,0,0,1,1.991.932,2.733,2.733,0,0,1,.867.868A2.146,2.146,0,0,1,15.6,13.873ZM10.558,9.627a.678.678,0,0,0,.219.52,2.569,2.569,0,0,0,.707.42V8.881Q10.559,9.017,10.558,9.627Zm2.884,4.354a.646.646,0,0,0-.244-.509,3.173,3.173,0,0,0-.732-.431v1.786Q13.441,14.662,13.442,13.981Z" stroke="none" fill="#3b82f6"></path>
<polyline points="5.346 7.929 6.932 2.237 1.135 2.966"></polyline>
<path data-cap="butt" d="M11.789,23A11,11,0,0,1,6.932,2.237"></path>
<polyline points="18.654 16.071 17.068 21.763 22.865 21.034"></polyline>
<path data-cap="butt" d="M12.211,1a11,11,0,0,1,4.857,20.763"></path>
</g>
</svg>
</div> </div>
<select class="pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="fee_to_extra"> <select class="pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="fee_to_extra">
<option value="0">None</option> <option value="0">None</option>
<option value="10" {% if data.fee_to_extra==10 %} selected{% endif %}>10%</option> <option value="10" {% if data.fee_from_extra==10 %} selected{% endif %}>10%</option>
<option value="50" {% if data.fee_to_extra==50 %} selected{% endif %}>50%</option> <option value="50" {% if data.fee_from_extra==50 %} selected{% endif %}>50%</option>
<option value="100" {% if data.fee_to_extra==100 %} selected{% endif %}>100%</option> <option value="100" {% if data.fee_from_extra==100 %} selected{% endif %}>100%</option>
</select> </select>
</div> </div>
</div> </div>
@@ -264,10 +380,10 @@
</div> </div>
</div> </div>
</div> </div>
<div class="py-0 border-b items-center justify-between -mx-4 mb-6 pb-3 border-gray-400 border-opacity-20"> <div class="py-3 border-b items-center justify-between -mx-4 mb-6 pb-6 border-gray-400 border-opacity-20">
<div class="w-full md:w-10/12"> <div class="w-full md:w-10/12">
<div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0"> <div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0">
<div class="w-full md:w-1/3 p-6"> <div class="w-full md:w-1/3 p-3">
<p class="text-sm text-coolGray-800 dark:text-white font-semibold">Bid Amount</p> <p class="text-sm text-coolGray-800 dark:text-white font-semibold">Bid Amount</p>
</div> </div>
<div class="w-full md:flex-1 p-3"> <div class="w-full md:flex-1 p-3">
@@ -276,17 +392,34 @@
<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 Bid Amount</p>
<div class="relative"> <div class="relative">
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_bid_amount_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
</div> <input class="cursor-not-allowed disabled-input pl-10 hover:border-blue-500 pl-10 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-white 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="amt_bid_min" name="amt_bid_min" value="{{ data.amt_bid_min }}" title="Bids with an amount below the minimum bid value will be discarded" readonly> <g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<rect x="9.843" y="5.379" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -0.7635 13.1569)" width="11.314" height="4.243"></rect>
<polyline points="3,23 3,19 15,19 15,23 "></polyline>
<line x1="4" y1="15" x2="1" y2="15" stroke="#3b82f6"></line>
<line x1="5.757" y1="10.757" x2="3.636" y2="8.636" stroke="#3b82f6"></line>
<line x1="1" y1="23" x2="17" y2="23"></line>
<line x1="17" y1="9" x2="23" y2="15"></line>
</g>
</svg>
</div>
<input class="cursor-not-allowed disabled-input pl-10 hover:border-blue-500 pl-10 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-white 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="amt_bid_min" name="amt_bid_min" value="{{ data.amt_bid_min }}" title="Bids with an amount below the minimum bid value will be discarded" readonly>
</div> </div>
</div> </div>
<div class="w-full md:w-1/2 p-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">Rate</p> <p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Rate</p>
<div class="relative"> <div class="relative">
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_rate_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g fill="#3b82f6">
<path d="M9,9h5L7,0,0,9H5V23a1,1,0,0,0,1,1H8a1,1,0,0,0,1-1Z" fill="#3b82f6"></path>
<path d="M14,17a3,3,0,1,1,3-3A3,3,0,0,1,14,17Zm0-4a1,1,0,1,0,1,1A1,1,0,0,0,14,13Z" data-color="color-2"></path>
<path d="M21,24a3,3,0,1,1,3-3A3,3,0,0,1,21,24Zm0-4a1,1,0,1,0,1,1A1,1,0,0,0,21,20Z" data-color="color-2"></path>
<path d="M13,23a1,1,0,0,1-.707-1.707l9-9a1,1,0,0,1,1.414,1.414l-9,9A1,1,0,0,1,13,23Z" data-color="color-2"></path>
</g>
</svg>
</div> </div>
<input class="cursor-not-allowed disabled-input pl-10 hover:border-blue-500 pl-10 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-white 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="rate" name="rate" value="{{ data.rate }}" readonly> <input class="cursor-not-allowed disabled-input pl-10 hover:border-blue-500 pl-10 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-white 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="rate" name="rate" value="{{ data.rate }}" onchange="set_rate('rate');" readonly>
</div> </div>
</div> </div>
</div> </div>
@@ -294,10 +427,10 @@
</div> </div>
</div> </div>
</div> </div>
<div class="py-0 border-b items-center justify-between -mx-4 mb-6 pb-3 border-gray-400 border-opacity-20"> <div class="py-3 border-b items-center justify-between -mx-4 mb-6 pb-6 border-gray-400 border-opacity-20">
<div class="w-full md:w-10/12"> <div class="w-full md:w-10/12">
<div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0"> <div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0">
<div class="w-full md:w-1/3 p-6"> <div class="w-full md:w-1/3 p-3">
<p class="text-sm text-coolGray-800 dark:text-white font-semibold">Time</p> <p class="text-sm text-coolGray-800 dark:text-white font-semibold">Time</p>
</div> </div>
<div class="w-full md:flex-1 p-3"> <div class="w-full md:flex-1 p-3">
@@ -306,7 +439,15 @@
<p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Offer valid (hrs)</p> <p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Offer valid (hrs)</p>
<div class="relative"> <div class="relative">
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ input_time_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path d="M15.6,13.873a2.273,2.273,0,0,1-.825,1.833,4.1,4.1,0,0,1-2.31.829v1.47h-.982V16.563a7.95,7.95,0,0,1-3.07-.617V14.053a8.328,8.328,0,0,0,1.5.545,8.019,8.019,0,0,0,1.568.28V12.654L11,12.468a5.357,5.357,0,0,1-2.012-1.216A2.332,2.332,0,0,1,8.4,9.627a2.123,2.123,0,0,1,.814-1.71,4.143,4.143,0,0,1,2.27-.812v-1.1h.982V7.074a8.126,8.126,0,0,1,2.97.66l-.674,1.678a7.768,7.768,0,0,0-2.3-.559v2.116a11.073,11.073,0,0,1,1.991.932,2.733,2.733,0,0,1,.867.868A2.146,2.146,0,0,1,15.6,13.873ZM10.558,9.627a.678.678,0,0,0,.219.52,2.569,2.569,0,0,0,.707.42V8.881Q10.559,9.017,10.558,9.627Zm2.884,4.354a.646.646,0,0,0-.244-.509,3.173,3.173,0,0,0-.732-.431v1.786Q13.441,14.662,13.442,13.981Z" stroke="none" fill="#3b82f6"></path>
<polyline points="5.346 7.929 6.932 2.237 1.135 2.966"></polyline>
<path data-cap="butt" d="M11.789,23A11,11,0,0,1,6.932,2.237"></path>
<polyline points="18.654 16.071 17.068 21.763 22.865 21.034"></polyline>
<path data-cap="butt" d="M12.211,1a11,11,0,0,1,4.857,20.763"></path>
</g>
</svg>
</div> </div>
<input class="pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" type="number" name="validhrs" min="1" max="48" value="{{ data.validhrs }}"> <input class="pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" type="number" name="validhrs" min="1" max="48" value="{{ data.validhrs }}">
</div> </div>
@@ -316,20 +457,34 @@
<p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Contract Locked (Mins)</p> <p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Contract Locked (Mins)</p>
<div class="relative"> <div class="relative">
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ input_time_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path d="M15.6,13.873a2.273,2.273,0,0,1-.825,1.833,4.1,4.1,0,0,1-2.31.829v1.47h-.982V16.563a7.95,7.95,0,0,1-3.07-.617V14.053a8.328,8.328,0,0,0,1.5.545,8.019,8.019,0,0,0,1.568.28V12.654L11,12.468a5.357,5.357,0,0,1-2.012-1.216A2.332,2.332,0,0,1,8.4,9.627a2.123,2.123,0,0,1,.814-1.71,4.143,4.143,0,0,1,2.27-.812v-1.1h.982V7.074a8.126,8.126,0,0,1,2.97.66l-.674,1.678a7.768,7.768,0,0,0-2.3-.559v2.116a11.073,11.073,0,0,1,1.991.932,2.733,2.733,0,0,1,.867.868A2.146,2.146,0,0,1,15.6,13.873ZM10.558,9.627a.678.678,0,0,0,.219.52,2.569,2.569,0,0,0,.707.42V8.881Q10.559,9.017,10.558,9.627Zm2.884,4.354a.646.646,0,0,0-.244-.509,3.173,3.173,0,0,0-.732-.431v1.786Q13.441,14.662,13.442,13.981Z" stroke="none" fill="#3b82f6"></path>
<polyline points="5.346 7.929 6.932 2.237 1.135 2.966"></polyline>
<path data-cap="butt" d="M11.789,23A11,11,0,0,1,6.932,2.237"></path>
<polyline points="18.654 16.071 17.068 21.763 22.865 21.034"></polyline>
<path data-cap="butt" d="M12.211,1a11,11,0,0,1,4.857,20.763"></path>
</g>
</svg>
</div> </div>
<input class="pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" type="number" name="lockmins" min="10" max="5000" value="{{ data.lockmins }}"> <input class="pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" type="number" name="lockmins" min="10" max="5000" value="{{ data.lockmins }}">
</div> </div>
{% if data.swap_style != 'xmr' %} {% if data.swap_style != 'xmr' %}
<div class="text-sm text-gray-500 mt-1.5">(Participate txn will be locked for half the time.)</div> <div class="text-sm text-gray-500 mt-1.5">(Participate txn will be locked for half the time.)</div>
{% endif %} {% endif %}
</div> </div> {% else %} <div class="w-full md:w-1/2 p-3">
{% else %}
<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">Contract locked (Hours)</p> <p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Contract locked (Hours)</p>
<div class="relative"> <div class="relative">
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ input_time_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path d="M15.6,13.873a2.273,2.273,0,0,1-.825,1.833,4.1,4.1,0,0,1-2.31.829v1.47h-.982V16.563a7.95,7.95,0,0,1-3.07-.617V14.053a8.328,8.328,0,0,0,1.5.545,8.019,8.019,0,0,0,1.568.28V12.654L11,12.468a5.357,5.357,0,0,1-2.012-1.216A2.332,2.332,0,0,1,8.4,9.627a2.123,2.123,0,0,1,.814-1.71,4.143,4.143,0,0,1,2.27-.812v-1.1h.982V7.074a8.126,8.126,0,0,1,2.97.66l-.674,1.678a7.768,7.768,0,0,0-2.3-.559v2.116a11.073,11.073,0,0,1,1.991.932,2.733,2.733,0,0,1,.867.868A2.146,2.146,0,0,1,15.6,13.873ZM10.558,9.627a.678.678,0,0,0,.219.52,2.569,2.569,0,0,0,.707.42V8.881Q10.559,9.017,10.558,9.627Zm2.884,4.354a.646.646,0,0,0-.244-.509,3.173,3.173,0,0,0-.732-.431v1.786Q13.441,14.662,13.442,13.981Z" stroke="none" fill="#3b82f6"></path>
<polyline points="5.346 7.929 6.932 2.237 1.135 2.966"></polyline>
<path data-cap="butt" d="M11.789,23A11,11,0,0,1,6.932,2.237"></path>
<polyline points="18.654 16.071 17.068 21.763 22.865 21.034"></polyline>
<path data-cap="butt" d="M12.211,1a11,11,0,0,1,4.857,20.763"></path>
</g>
</svg>
</div> </div>
<input class="pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" type="number" name="lockhrs" min="1" max="96" value="{{ data.lockhrs }}"> <input class="pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" type="number" name="lockhrs" min="1" max="96" value="{{ data.lockhrs }}">
</div> </div>
@@ -343,10 +498,10 @@
</div> </div>
</div> </div>
</div> </div>
<div class="py-0 border-b items-center justify-between -mx-4 mb-6 pb-3 border-gray-400 border-opacity-20"> <div class="py-3 border-b items-center justify-between -mx-4 mb-6 pb-6 border-gray-400 border-opacity-20">
<div class="w-full md:w-10/12"> <div class="w-full md:w-10/12">
<div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0"> <div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0">
<div class="w-full md:w-1/3 p-6"> <div class="w-full md:w-1/3 p-3">
<p class="text-sm text-coolGray-800 dark:text-white font-semibold">Strategy</p> <p class="text-sm text-coolGray-800 dark:text-white font-semibold">Strategy</p>
</div> </div>
<div class="w-full md:flex-1 p-3"> <div class="w-full md:flex-1 p-3">
@@ -354,9 +509,21 @@
<div class="w-full md:w-1/2 p-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">Auto Accept Strategy</p> <p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Auto Accept Strategy</p>
<div class="relative"> <div class="relative">
{{ input_down_arrow_offer_svg | safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"> <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_auto_strategy_svg | safe }} <svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<circle cx="12" cy="12" r="5" stroke="#3b82f6" data-cap="butt"></circle>
<polygon points="5 6 2 4 5 2 5 6" fill="#3b82f6" stroke="none"></polygon>
<polygon points="19 18 22 20 19 22 19 18" fill="#3b82f6" stroke="none"></polygon>
<polygon points="5 6 2 4 5 2 5 6"></polygon>
<line x1="5" y1="4" x2="9" y2="4"></line>
<polygon points="19 18 22 20 19 22 19 18"></polygon>
<line x1="19" y1="20" x2="15" y2="20"></line>
</g>
</svg>
</div> </div>
<select class="pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="automation_strat_id"> <select class="pl-10 hover:border-blue-500 pl-10 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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="automation_strat_id">
<option value="-1" {% if data.automation_strat_id==-1 %} selected{% endif %}>None</option> <option value="-1" {% if data.automation_strat_id==-1 %} selected{% endif %}>None</option>
@@ -371,29 +538,20 @@
</div> </div>
</div> </div>
</div> </div>
<div class="py-0 border-b items-center justify-between -mx-4 mb-6 pb-3 border-gray-400 border-opacity-20"> <div class="py-3 border-b items-center justify-between -mx-4 mb-6 pb-6 border-gray-400 border-opacity-20">
<div class="w-full md:w-10/12"> <div class="w-full md:w-10/12">
<div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0"> <div class="flex flex-wrap -m-3 w-full sm:w-auto px-4 mb-6 sm:mb-0">
<div class="w-full md:w-1/3 p-6"> <div class="w-full md:w-1/3 p-3">
<p class="text-sm text-coolGray-800 dark:text-white font-semibold">Options</p> <p class="text-sm text-coolGray-800 dark:text-white font-semibold">Options</p>
</div> </div>
<div class="w-full md:flex-1 p-3"> <div class="w-full md:flex-1 p-3">
<div class="flex form-check form-check-inline"> <div class="form-check form-check-inline">
<div class="flex items-center h-5"> <input class="cursor-not-allowed disabled-input 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="amt_var" name="amt_var" value="av" {% if data.amt_var==true %} checked="checked" {% endif %} disabled>
<input class="cursor-not-allowed 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="amt_var" name="amt_var" value="av" {% if data.amt_var==true %} checked="checked" {% endif %} disabled> <label class="form-check-label ml-2 text-sm font-medium text-gray-800 dark:text-white" for="inlineCheckbox2">Amount Variable</label>
</div>
<div class="ml-2 text-sm">
<label class="form-check-label text-sm font-medium text-gray-800 dark:text-white" for="inlineCheckbox2" style="opacity: 0.40;">Amount Variable</label>
<p id="helper-checkbox-text" class="text-xs font-normal text-gray-500 dark:text-gray-300" style="opacity: 0.40;">Allow bids with a different amount to the offer.</p>
</div>
</div>
<div class="flex mt-2 form-check form-check-inline">
<div class="flex items-center h-5">
<input class="cursor-not-allowed 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="rate_var" name="rate_var" value="rv" {% if data.rate_var==true %} checked="checked" {% endif %} disabled> </div>
<div class="ml-2 text-sm">
<label class="form-check-label text-sm font-medium text-gray-800 dark:text-white" for="inlineCheckbox3" style="opacity: 0.40;">Rate Variable</label>
<p id="helper-checkbox-text" class="text-xs font-normal text-gray-500 dark:text-gray-300" style="opacity: 0.40;">Allow bids with a different rate to the offer.</p>
</div> </div>
<div class="form-check form-check-inline mt-2">
<input class="cursor-not-allowed disabled-input 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="rate_var" name="rate_var" value="rv" {% if data.rate_var==true %} checked="checked" {% endif %} disabled>
<label class="form-check-label ml-2 text-sm font-medium text-gray-800 dark:text-white" for="inlineCheckbox3">Rate Variable</label>
</div> </div>
</div> </div>
</div> </div>
@@ -418,6 +576,12 @@
</div> </div>
<div class="w-full md:w-auto p-1.5"> <div class="w-full md:w-auto p-1.5">
<button name="check_offer" value="Continue" 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"> <button name="check_offer" value="Continue" 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">
<svg class="mr-2" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
<circle cx="12" cy="12" r="11"></circle>
<polyline points="11 8 15 12 11 16" stroke="#ffffff"></polyline>
</g>
</svg>
<span>Continue</span> <span>Continue</span>
</button> </button>
</div> </div>
@@ -438,15 +602,91 @@
<input type="hidden" name="coin_to" value="{{ data.coin_to }}"> <input type="hidden" name="coin_to" value="{{ data.coin_to }}">
{% if data.amt_var==true %} {% if data.amt_var==true %}
<input type="hidden" name="amt_var" value="true"> <input type="hidden" name="amt_var" value="true">
{% endif %} {% if data.rate_var==true %} {% endif %}
{% if data.rate_var==true %}
<input type="hidden" name="rate_var" value="true"> <input type="hidden" name="rate_var" value="true">
{% endif %} {% endif %}
</form> </form>
<script src="static/js/new_offer.js"></script> <script>
const selects = document.querySelectorAll('select.disabled-select');
for (const select of selects) {
if (select.disabled) {
select.classList.add('disabled-select-enabled');
} else {
select.classList.remove('disabled-select-enabled');
}
}
</script>
<script>
const inputs = document.querySelectorAll('input.disabled-input, input[type="checkbox"].disabled-input');
for (const input of inputs) {
if (input.readOnly) {
input.classList.add('disabled-input-enabled');
} else {
input.classList.remove('disabled-input-enabled');
}
}
</script>
<style>
.disabled-input-enabled {
opacity: 0.50 !important;
}
select.disabled-select-enabled {
opacity: 0.50 !important;
}
</style>
<script src="static/js/new_offer.js"></script>
<style>
.custom-select .select {
appearance: none;
background-position: 10px center;
background-repeat: no-repeat;
position: relative;
}
.custom-select select::-webkit-scrollbar {
width: 0;
}
.custom-select .select option {
padding-left: 0;
text-indent: 0;
background-repeat: no-repeat;
background-position: 0 50%;
}
.custom-select .select option.no-space {
padding-left: 0;
}
.custom-select .select option[data-image] {
background-image: url('');
}
.custom-select .select-icon {
position: absolute;
top: 50%;
left: 10px;
transform: translateY(-50%);
}
.custom-select .select-image {
display: none;
margin-top: 10px;
}
.custom-select .select:focus+.select-dropdown .select-image {
display: block;
}
</style>
<script src="static/js/coin_icons.js"></script>
<script src="static/js/coin_icons_2.js"></script>
</div> </div>
</div> </div>
</div> </div>
</div> </div>{% include 'footer.html' %}
{% include 'footer.html' %}
</body> </body>
</html> </html>

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,4 @@
{% include 'header.html' %} {% include 'header.html' %}
{% from 'style.html' import breadcrumb_line_svg, input_arrow_down_svg %}
<div class="container mx-auto"> <div class="container mx-auto">
<section class="p-5 mt-5"> <section class="p-5 mt-5">
<div class="flex flex-wrap items-center -m-2"> <div class="flex flex-wrap items-center -m-2">
@@ -10,11 +9,19 @@
<p>Home</p> <p>Home</p>
</a> </a>
</li> </li>
<li> {{ breadcrumb_line_svg | safe }} </li> <li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
<li> <li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/rpc">RPC Console</a> <a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/rpc">RPC Console</a>
</li> </li>
<li> {{ breadcrumb_line_svg | safe }} </li> <li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
</ul> </ul>
</div> </div>
</div> </div>
@@ -28,6 +35,7 @@
<div class="relative z-20 flex flex-wrap items-center -m-3"> <div class="relative z-20 flex flex-wrap items-center -m-3">
<div class="w-full md:w-1/2 p-3"> <div class="w-full md:w-1/2 p-3">
<h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">RPC Console</h2> <h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">RPC Console</h2>
<p class="font-normal text-coolGray-200 dark:text-white">Manage your BasicSwap client and coins settings.</p>
</div> </div>
</div> </div>
</div> </div>
@@ -62,8 +70,10 @@
<tr class="opacity-100 text-gray-500 dark:text-gray-100"> <tr class="opacity-100 text-gray-500 dark:text-gray-100">
<td class="py-3 px-6"> <td class="py-3 px-6">
<div class="relative"> <div class="relative">
{{ input_arrow_down_svg| safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<select 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" name="coin_type" id="coin_type" onchange="set_coin();"> <path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<select 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" name="coin_type">
<option value="-1" {% if coin_type==-1 %} selected{% endif %}>Select Coin</option> <option value="-1" {% if coin_type==-1 %} selected{% endif %}>Select Coin</option>
{% for c in coins %} {% for c in coins %}
<option value="{{ c[0] }}" {% if coin_type==c[0] %} selected{% endif %}>{{ c[1] }}</option> <option value="{{ c[0] }}" {% if coin_type==c[0] %} selected{% endif %}>{{ c[1] }}</option>
@@ -72,21 +82,23 @@
</div> </div>
</td> </td>
<td class="py-3 px-6"> <td class="py-3 px-6">
<input 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" type="text" name="cmd" id="cmd" oninput="set_method();"> <input 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" type="text" name="cmd">
</td> </td>
</tr> </tr>
<tr class="opacity-100 text-gray-500 dark:text-gray-100"> <tr class="opacity-100 text-gray-500 dark:text-gray-100">
<td class="py-3 px-6"> <td class="py-3 px-6">
<div class="relative"> <div class="relative">
{{ input_arrow_down_svg| safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<select 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" name="call_type" id="call_type" > <path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<select 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" name="call_type">
<option value="cli" {% if call_type=="cli" %} selected{% endif %}>CLI</option> <option value="cli" {% if call_type=="cli" %} selected{% endif %}>CLI</option>
<option value="http" {% if call_type=="http" %} selected{% endif %}>HTTP</option> <option value="http" {% if call_type=="http" %} selected{% endif %}>HTTP</option>
</select> </select>
</div> </div>
</td> </td>
<td class="py-3 px-6"> <td class="py-3 px-6">
<input 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" type="text" name="type_map" id="type_map" title="Convert inputs when using http. Example: 'sifbj' 1st parameter is a string, 2nd is converted to an int, 3rd to float then boolean and json object or array"> <input 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" type="text" name="type_map" title="Convert inputs when using http. Example: 'sibj' 1st parameter is a string, 2nd is converted to an int then boolean and json object or array">
</td> </td>
</table> </table>
</div> </div>
@@ -109,7 +121,13 @@
<div class="px-6"> <div class="px-6">
<div class="flex flex-wrap justify-end"> <div class="flex flex-wrap justify-end">
<div class="w-full md:w-auto p-1.5 ml-2"> <div class="w-full md:w-auto p-1.5 ml-2">
<button name="apply" value="Apply" 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">Apply</button> <button name="apply" value="Apply" 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">
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
<polyline points=" 6,12 10,16 18,8 " stroke="#ffffff"></polyline>
<circle cx="12" cy="12" r="11"></circle>
</g>
</svg>Apply </button>
</div> </div>
</div> </div>
</div> </div>
@@ -120,15 +138,14 @@
</div> </div>
</div> </div>
</section> </section>
{% if result %} {% if result %}
<section class="rounded-xl"> <section>
<div class="pl-6 pr-6 pt-0 pb-0 h-full overflow-hidden"> <div class="pl-6 pr-6 pt-0 pb-0 h-full overflow-hidden">
<div class="border-coolGray-100"> <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 -m-2">
<div class="w-full pt-2"> <div class="w-full pt-2">
<div class="container mt-5 mx-auto"> <div class="container mt-5 mx-auto">
<div class="pt-6 bg-coolGray-100 dark:bg-gray-500 rounded-xl rounded-bl-none rounded-br-none"> <div class="pt-6 pb-6 bg-coolGray-100 dark:bg-gray-500 rounded-xl">
<div class="px-6"> <div class="px-6">
<div class="w-full mt-6 pb-6 overflow-x-auto"> <div class="w-full mt-6 pb-6 overflow-x-auto">
<table class="w-full min-w-max text-sm"> <table class="w-full min-w-max text-sm">
@@ -136,7 +153,7 @@
<tr class="text-left"> <tr class="text-left">
<th class="p-0"> <th class="p-0">
<div class="py-3 px-6 rounded-tl-xl bg-coolGray-200 dark:bg-gray-600"> <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">RPC Console Output:</span> <span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">RPC Console Output</span>
</div> </div>
</th> </th>
</tr> </tr>
@@ -149,55 +166,14 @@
</table> </table>
</div> </div>
</div> </div>
{% endif %}
</form> </form>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<section>
<div class="pl-6 pr-6 pt-0 pb-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 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">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
{% endif %}
</div> </div>
{% include 'footer.html' %} {% include 'footer.html' %}
</body> </body>
<script>
function set_method() {
const coin_type = document.getElementById('coin_type').value;
if (coin_type == 4 || coin_type == -6) {
const cmd = document.getElementById('cmd');
const type_map = document.getElementById('type_map');
let method = cmd.value.split(' ')[0];
if (method == 'sendtoaddress') {
type_map.value = 'sf';
}
}
}
function set_coin() {
const coin_type = document.getElementById('coin_type').value;
let call_type = document.getElementById('call_type');
if (coin_type == 4 || coin_type == -6) {
call_type.disabled = true;
call_type.value = 'http';
} else {
call_type.disabled = false;
}
set_method();
}
</script>
</html> </html>

View File

@@ -1,5 +1,4 @@
{% include 'header.html' %} {% include 'header.html' %}
{% from 'style.html' import breadcrumb_line_svg, input_arrow_down_svg %}
<div class="container mx-auto"> <div class="container mx-auto">
<section class="p-5 mt-5"> <section class="p-5 mt-5">
<div class="flex flex-wrap items-center -m-2"> <div class="flex flex-wrap items-center -m-2">
@@ -10,11 +9,17 @@
<p>Home</p> <p>Home</p>
</a> </a>
</li> </li>
<li> {{ breadcrumb_line_svg | safe }} </li> <li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
<li> <li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/settings">Settings</a> <a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/settings">Settings</a>
</li> </li>
<li> {{ breadcrumb_line_svg | safe }} </li> <svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</ul> </ul>
</div> </div>
</div> </div>
@@ -40,16 +45,16 @@
<div class="pb-6"> <div class="pb-6">
<div class="flex flex-wrap items-center justify-between -m-2"> <div class="flex flex-wrap items-center justify-between -m-2">
<div class="w-full pt-2"> <div class="w-full pt-2">
<div class="mb-4 border-b pb-5 border-gray-200 dark:border-gray-500"> <div class="text-sm font-medium text-center text-gray-500 border-b border-gray-200 dark:text-gray-400 dark:border-gray-700">
<ul class="flex flex-wrap text-sm font-medium text-center text-gray-500 dark:text-gray-400" id="myTab" data-tabs-toggle="#settingstab" role="tablist"> <ul class="flex flex-wrap -mb-px" id="myTab" data-tabs-toggle="#settingstab" role="tablist">
<li class="mr-2"> <li class="mr-2" role="presentation">
<a class="inline-block px-4 py-3 rounded-lg hover:text-gray-900 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white" id="coins-tab" data-tabs-target="#coins" role="tab" aria-controls="coins" aria-selected={% if active_tab == 'default' %}"true"{% else %}"false"{% endif %}>Coins</a> <a class="inline-block p-4 border-b-2 border-transparent rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300" id="coins-tab" data-tabs-target="#coins" role="tab" aria-controls="coins" aria-selected={% if active_tab == 'default' %}"true"{% else %}"false"{% endif %}>Coins</a>
</li> </li>
<li class="mr-2"> <li class="mr-2" role="presentation">
<a class="inline-block px-4 py-3 rounded-lg hover:text-gray-900 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white" id="general-tab" data-tabs-target="#general" role="tab" aria-controls="general" aria-selected={% if active_tab == 'general' %}"true"{% else %}"false"{% endif %}>General</a> <a class="inline-block p-4 border-b-2 border-transparent rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300" id="general-tab" data-tabs-target="#general" role="tab" aria-controls="general" aria-selected={% if active_tab == 'general' %}"true"{% else %}"false"{% endif %}>General</a>
</li> </li>
<li class="mr-2"> <li class="mr-2" role="presentation">
<a class="inline-block px-4 py-3 rounded-lg hover:text-gray-900 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white" id="tor-tab" data-tabs-target="#tor" role="tab" aria-controls="tor" aria-selected={% if active_tab == 'tor' %}"true"{% else %}"false"{% endif %}>Tor</a> <a class="inline-block p-4 border-b-2 border-transparent rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300" id="tor-tab" data-tabs-target="#tor" role="tab" aria-controls="tor" aria-selected={% if active_tab == 'tor' %}"true"{% else %}"false"{% endif %}>Tor</a>
</li> </li>
</ul> </ul>
</div> </div>
@@ -110,7 +115,9 @@
<td class="py-3 px-6 bold">Manage Daemon</td> <td class="py-3 px-6 bold">Manage Daemon</td>
<td class="py-3 px-6"> <td class="py-3 px-6">
<div class="relative"> <div class="relative">
{{ input_arrow_down_svg| safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<select 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" name="managedaemon_{{ c.name }}"> <select 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" name="managedaemon_{{ c.name }}">
<option value="true" {% if c.manage_daemon==true %} selected{% endif %}>True</option> <option value="true" {% if c.manage_daemon==true %} selected{% endif %}>True</option>
<option value="false" {% if c.manage_daemon==false %} selected{% endif %}>False</option> <option value="false" {% if c.manage_daemon==false %} selected{% endif %}>False</option>
@@ -141,7 +148,9 @@
<td class="py-3 px-6"> <td class="py-3 px-6">
<div class="w-52 md:flex-1"> <div class="w-52 md:flex-1">
<div class="relative"> <div class="relative">
{{ input_arrow_down_svg| safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<select 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" name="autosetdaemon_{{ c.name }}"> <select 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" name="autosetdaemon_{{ c.name }}">
<option value="true" {% if c.autosetdaemon==true %} selected{% endif %}>True</option> <option value="true" {% if c.autosetdaemon==true %} selected{% endif %}>True</option>
<option value="false" {% if c.autosetdaemon==false %} selected{% endif %}>False</option> <option value="false" {% if c.autosetdaemon==false %} selected{% endif %}>False</option>
@@ -167,7 +176,9 @@
<td class="py-3 px-6 bold">Chain Lookups</td> <td class="py-3 px-6 bold">Chain Lookups</td>
<td class="py-3 px-6"> <td class="py-3 px-6">
<div class="relative"> <div class="relative">
{{ input_arrow_down_svg| safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<select 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" name="lookups_{{ c.name }}"> <select 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" name="lookups_{{ c.name }}">
<option value="local" {% if c.lookups=='local' %} selected{% endif %}>Local Node</option> <option value="local" {% if c.lookups=='local' %} selected{% endif %}>Local Node</option>
<option value="explorer" {% if c.lookups=='explorer' %} selected{% endif %}>Explorer</option> <option value="explorer" {% if c.lookups=='explorer' %} selected{% endif %}>Explorer</option>
@@ -180,12 +191,14 @@
<td class="py-3 px-6 bold">Transaction Fee Priority</td> <td class="py-3 px-6 bold">Transaction Fee Priority</td>
<td class="py-3 px-6"> <td class="py-3 px-6">
<div class="relative"> <div class="relative">
{{ input_arrow_down_svg| safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<select 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" name="fee_priority_{{ c.name }}"> <select 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" name="fee_priority_{{ c.name }}">
<option value="0" {% if c.fee_priority==0 %} selected{% endif %}>Auto</option> <option value="0" {% if c.fee_priority==0 %} selected{% endif %}>Default</option>
<option value="1" {% if c.fee_priority==1 %} selected{% endif %}>Slow</option> <option value="1" {% if c.fee_priority==1 %} selected{% endif %}>Low</option>
<option value="2" {% if c.fee_priority==2 %} selected{% endif %}>Normal</option> <option value="2" {% if c.fee_priority==2 %} selected{% endif %}>Medium</option>
<option value="3" {% if c.fee_priority==3 %} selected{% endif %}>Fast</option> <option value="3" {% if c.fee_priority==3 %} selected{% endif %}>High</option>
</select> </select>
</div> </div>
</td> </td>
@@ -285,7 +298,9 @@
<td class="py-3 px-6 bold w-96 bold">Debug Mode</td> <td class="py-3 px-6 bold w-96 bold">Debug Mode</td>
<td class="py-3 px-6"> <td class="py-3 px-6">
<div class="relative"> <div class="relative">
{{ input_arrow_down_svg| safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<select name="debugmode" 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"> <select name="debugmode" 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">
<option {% if general_settings.debug %}selected{% endif %} value="true">True</option> <option {% if general_settings.debug %}selected{% endif %} value="true">True</option>
<option {% if not general_settings.debug %}selected{% endif %} value="false">False</option> <option {% if not general_settings.debug %}selected{% endif %} value="false">False</option>
@@ -297,7 +312,9 @@
<td class="py-3 px-6 bold">Debug Mode UI</td> <td class="py-3 px-6 bold">Debug Mode UI</td>
<td class="py-3 px-6"> <td class="py-3 px-6">
<div class="relative"> <div class="relative">
{{ input_arrow_down_svg| safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<select name="debugui" 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"> <select name="debugui" 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">
<option {% if general_settings.debug_ui %}selected{% endif %} value="true">True</option> <option {% if general_settings.debug_ui %}selected{% endif %} value="true">True</option>
<option {% if not general_settings.debug_ui %}selected{% endif %} value="false">False</option> <option {% if not general_settings.debug_ui %}selected{% endif %} value="false">False</option>
@@ -309,7 +326,9 @@
<td class="py-3 px-6 bold">Remove DB records for expired offers</td> <td class="py-3 px-6 bold">Remove DB records for expired offers</td>
<td class="py-3 px-6"> <td class="py-3 px-6">
<div class="relative"> <div class="relative">
{{ input_arrow_down_svg| safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<select name="expire_db_records" 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"> <select name="expire_db_records" 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">
<option {% if general_settings.expire_db_records %}selected{% endif %} value="true">True</option> <option {% if general_settings.expire_db_records %}selected{% endif %} value="true">True</option>
<option {% if not general_settings.expire_db_records %}selected{% endif %} value="false">False</option> <option {% if not general_settings.expire_db_records %}selected{% endif %} value="false">False</option>
@@ -386,7 +405,9 @@
<td class="py-3 px-6 bold w-96 bold">Show Price Chart</td> <td class="py-3 px-6 bold w-96 bold">Show Price Chart</td>
<td class="py-3 px-6"> <td class="py-3 px-6">
<div class="relative"> <div class="relative">
{{ input_arrow_down_svg| safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<select name="showchart" 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"> <select name="showchart" 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">
<option {% if chart_settings.show_chart %}selected{% endif %} value="true">True</option> <option {% if chart_settings.show_chart %}selected{% endif %} value="true">True</option>
<option {% if not chart_settings.show_chart %}selected{% endif %} value="false">False</option> <option {% if not chart_settings.show_chart %}selected{% endif %} value="false">False</option>
@@ -395,30 +416,12 @@
</td> </td>
</tr> </tr>
<tr class="opacity-100 text-gray-500 dark:text-gray-100"> <tr class="opacity-100 text-gray-500 dark:text-gray-100">
<td class="py-3 px-6 bold">Chart API Key (CryptoCompare)</td> <td class="py-3 px-6 bold">Chart API Key</td>
<td class="py-3 px-6"> <td class="py-3 px-6">
<label for="chartapikey" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Chart API (free) Key at <a class="inline-block text-blue-500 hover:text-blue-600 hover:underline" href="https://min-api.cryptocompare.com/" target="_blank">CryptoCompare.com</a> <label for="message" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Chart API (free) Key at <a class="inline-block text-blue-500 hover:text-blue-600 hover:underline" href="https://min-api.cryptocompare.com/" target="_blank">CryptoCompare.com</a>
<br /> <br />
</label> </label>
<input name="chartapikey" type="text" 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" min="3" max="32" value="{{chart_settings.chart_api_key}}"> <input name="chartapikey" type="text" 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" name="" min="3" max="32" value="{{chart_settings.chart_api_key}}">
</td>
</tr>
<tr class="opacity-100 text-gray-500 dark:text-gray-100">
<td class="py-3 px-6 bold">Chart API Key (CoinGecko)</td>
<td class="py-3 px-6">
<label for="coingeckoapikey" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Chart API (free) Key at <a class="inline-block text-blue-500 hover:text-blue-600 hover:underline" href="https://coingecko.com/" target="_blank">CoinGecko.com</a>
<br />
</label>
<input name="coingeckoapikey" type="text" 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" min="3" max="32" value="{{chart_settings.coingecko_api_key}}">
</td>
</tr>
<tr class="opacity-100 text-gray-500 dark:text-gray-100">
<td class="py-3 px-6 bold">Enabled Coins</td>
<td class="py-3 px-6">
<label for="enabledchartcoins" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Coins to show data for: Blank for active coins, "all" for all known coins or comma separated list of coin tickers to show
<br />
</label>
<input name="enabledchartcoins" type="text" 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" value="{{chart_settings.enabled_chart_coins}}">
</td> </td>
</tr> </tr>
</table> </table>
@@ -493,7 +496,9 @@
<td class="py-3 px-6"> <td class="py-3 px-6">
<div class="w-1/5 md:flex-1"> <div class="w-1/5 md:flex-1">
<div class="relative"> <div class="relative">
{{ input_arrow_down_svg| safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<select name="usetorproxy" 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"> <select name="usetorproxy" 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">
<option {% if tor_settings.use_tor %}selected{% endif %} value="true">True</option> <option {% if tor_settings.use_tor %}selected{% endif %} value="true">True</option>
<option {% if not tor_settings.use_tor %}selected{% endif %} value="false">False</option> <option {% if not tor_settings.use_tor %}selected{% endif %} value="false">False</option>

View File

@@ -1,5 +1,4 @@
{% include 'header.html' %} {% include 'header.html' %}
{% from 'style.html' import breadcrumb_line_svg, input_arrow_down_svg, filter_apply_svg, circle_plus_svg, page_forwards_svg, page_back_svg %}
<div class="container mx-auto"> <div class="container mx-auto">
<section class="p-5 mt-5"> <section class="p-5 mt-5">
<div class="flex flex-wrap items-center -m-2"> <div class="flex flex-wrap items-center -m-2">
@@ -10,11 +9,19 @@
<p>Home</p> <p>Home</p>
</a> </a>
</li> </li>
<li>{{ breadcrumb_line_svg | safe }}</li> <li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
<li> <li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/smsgaddresses">SMSG Addresses</a> <a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/smsgaddresses">SMSG Addresses</a>
</li> </li>
<li>{{ breadcrumb_line_svg | safe }}</li> <li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
</ul> </ul>
</div> </div>
</div> </div>
@@ -36,13 +43,13 @@
</section> </section>
{% include 'inc_messages.html' %} {% include 'inc_messages.html' %}
<form method="post"> <form method="post">
{% if data.edit_address %} {% if data.edit_address %}
<input type="hidden" name="edit_address_id" value="{{ data.addr_data.id }}"> <input type="hidden" name="edit_address_id" value="{{ data.addr_data.id }}">
<input type="hidden" name="edit_address" value="{{ data.addr_data.addr }}"> <input type="hidden" name="edit_address" value="{{ data.addr_data.addr }}">
<section class="p-6 bg-body dark:bg-gray-700"> <section class="p-6 bg-body dark:bg-gray-700">
<div class="flex flex-wrap items-center"> <div class="flex flex-wrap items-center">
<div class="w-full"> <div class="w-full">
<h4 class="text-black dark:text-white text-2xl"><span class="bold">Edit Address:</span><span class="monospace"> {{ data.addr_data.addr }}</span></h4> <h4 class="font-semibold text-black dark:text-white text-2xl">Edit Address: {{ data.addr_data.addr }}</h4>
</div> </div>
</div> </div>
</section> </section>
@@ -78,7 +85,9 @@
<td class="py-3 px-6">Active</td> <td class="py-3 px-6">Active</td>
<td class="py-3 px-6"> <td class="py-3 px-6">
<div class="relative"> <div class="relative">
{{ input_arrow_down_svg| safe }} <svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
<select 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" name="active_ind"> <select 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" name="active_ind">
<option value="1" {% if data.addr_data.active_ind==1 %} selected{% endif %}>True</option> <option value="1" {% if data.addr_data.active_ind==1 %} selected{% endif %}>True</option>
<option value="0" {% if data.addr_data.active_ind==0 %} selected{% endif %}>False</option> <option value="0" {% if data.addr_data.active_ind==0 %} selected{% endif %}>False</option>
@@ -112,10 +121,24 @@
<div class="px-6"> <div class="px-6">
<div class="flex flex-wrap justify-end"> <div class="flex flex-wrap justify-end">
<div class="w-full md:w-auto p-1.5 ml-2"> <div class="w-full md:w-auto p-1.5 ml-2">
<button name="saveaddr" value="Save Address" 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">Save Address</button> <button name="saveaddr" value="Save Address" 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">
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="square" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="miter" class="nc-icon-wrapper" stroke-miterlimit="10">
<line x1="12" y1="7" x2="12" y2="17" stroke="#ffffff"></line>
<line x1="17" y1="12" x2="7" y2="12" stroke="#ffffff"></line>
<circle cx="12" cy="12" r="11"></circle>
</g>
</svg>Save Address </button>
</div> </div>
<div class="w-full md:w-auto p-1.5 ml-2"> <div class="w-full md:w-auto p-1.5 ml-2">
<button name="cancel" value="Cancel" 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">Back</button> <button name="cancel" value="Cancel" 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">
<svg class="text-gray-500 w-5 h-5 mr-2" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="square" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="miter" class="nc-icon-wrapper" stroke-miterlimit="10">
<line data-cap="butt" x1="18" y1="12" x2="7" y2="12" stroke-linecap="butt" stroke="#ffffff"></line>
<polyline points=" 11,16 7,12 11,8 " stroke="#ffffff"></polyline>
<circle cx="12" cy="12" r="11"></circle>
</g>
</svg>Go Back </button>
</div> </div>
</div> </div>
</div> </div>
@@ -184,10 +207,24 @@
<div class="px-6"> <div class="px-6">
<div class="flex flex-wrap justify-end"> <div class="flex flex-wrap justify-end">
<div class="w-full md:w-auto p-1.5 ml-2"> <div class="w-full md:w-auto p-1.5 ml-2">
<button name="createnewaddr" value="Create Address" 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">Create Address</button> <button name="createnewaddr" value="Create Address" 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">
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="square" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="miter" class="nc-icon-wrapper" stroke-miterlimit="10">
<line x1="12" y1="7" x2="12" y2="17" stroke="#ffffff"></line>
<line x1="17" y1="12" x2="7" y2="12" stroke="#ffffff"></line>
<circle cx="12" cy="12" r="11"></circle>
</g>
</svg>Create Address</button>
</div> </div>
<div class="w-full md:w-auto p-1.5 ml-2"> <div class="w-full md:w-auto p-1.5 ml-2">
<button name="cancel" value="Cancel" 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">Back</button> <button name="cancel" value="Cancel" 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">
<svg class="text-gray-500 w-5 h-5 mr-2" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="square" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="miter" class="nc-icon-wrapper" stroke-miterlimit="10">
<line data-cap="butt" x1="18" y1="12" x2="7" y2="12" stroke-linecap="butt" stroke="#ffffff"></line>
<polyline points=" 11,16 7,12 11,8 " stroke="#ffffff"></polyline>
<circle cx="12" cy="12" r="11"></circle>
</g>
</svg>Go Back</button>
</div> </div>
</div> </div>
</div> </div>
@@ -262,10 +299,24 @@
<div class="px-6"> <div class="px-6">
<div class="flex flex-wrap justify-end"> <div class="flex flex-wrap justify-end">
<div class="w-full md:w-auto p-1.5 ml-2"> <div class="w-full md:w-auto p-1.5 ml-2">
<button name="createnewsendaddr" value="Add Address" 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">Create Address</button> <button name="createnewsendaddr" value="Add Address" 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">
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="square" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="miter" class="nc-icon-wrapper" stroke-miterlimit="10">
<line x1="12" y1="7" x2="12" y2="17" stroke="#ffffff"></line>
<line x1="17" y1="12" x2="7" y2="12" stroke="#ffffff"></line>
<circle cx="12" cy="12" r="11"></circle>
</g>
</svg>Create Address</button>
</div> </div>
<div class="w-full md:w-auto p-1.5 ml-2"> <div class="w-full md:w-auto p-1.5 ml-2">
<button name="cancel" value="Cancel" 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">Back</button> <button name="cancel" value="Cancel" 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">
<svg class="text-gray-500 w-5 h-5 mr-2" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="square" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="miter" class="nc-icon-wrapper" stroke-miterlimit="10">
<line data-cap="butt" x1="18" y1="12" x2="7" y2="12" stroke-linecap="butt" stroke="#ffffff"></line>
<polyline points=" 11,16 7,12 11,8 " stroke="#ffffff"></polyline>
<circle cx="12" cy="12" r="11"></circle>
</g>
</svg>Go Back</button>
</div> </div>
</div> </div>
</div> </div>
@@ -309,21 +360,15 @@
<tr class="opacity-100 text-gray-500 dark:text-gray-100"> <tr class="opacity-100 text-gray-500 dark:text-gray-100">
<td class="py-3 px-6 bold"> Sort by: </td> <td class="py-3 px-6 bold"> Sort by: </td>
<td class="py-3 px-6"> <td class="py-3 px-6">
<div class="relative">
{{ input_arrow_down_svg| safe }}
<select 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" name="sort_by"> <select 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" name="sort_by">
<option value="created_at" {% if filters.sort_by=='created_at' %} selected{% endif %}>Created At</option> <option value="created_at" {% if filters.sort_by=='created_at' %} selected{% endif %}>Created At</option>
</select> </select>
</div>
</td> </td>
<td class="py-3 px-6"> <td class="py-3 px-6">
<div class="relative">
{{ input_arrow_down_svg| safe }}
<select 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" name="sort_dir"> <select 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" name="sort_dir">
<option value="asc" {% if filters.sort_dir=='asc' %} selected{% endif %}>Ascending</option> <option value="asc" {% if filters.sort_dir=='asc' %} selected{% endif %}>Ascending</option>
<option value="desc" {% if filters.sort_dir=='desc' %} selected{% endif %}>Descending</option> <option value="desc" {% if filters.sort_dir=='desc' %} selected{% endif %}>Descending</option>
</select> </select>
</div>
</td> </td>
</tr> </tr>
<tr class="opacity-100 text-gray-500 dark:text-gray-100"> <tr class="opacity-100 text-gray-500 dark:text-gray-100">
@@ -336,15 +381,12 @@
<tr class="opacity-100 text-gray-500 dark:text-gray-100"> <tr class="opacity-100 text-gray-500 dark:text-gray-100">
<td class="py-3 px-6">Type</td> <td class="py-3 px-6">Type</td>
<td class="py-3 px-6"> <td class="py-3 px-6">
<div class="relative">
{{ input_arrow_down_svg| safe }}
<select 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" name="filter_addr_type"> <select 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" name="filter_addr_type">
<option{% if filters.addr_type=="-1" %} selected{% endif %} value="-1">Any</option> <option{% if filters.addr_type=="-1" %} selected{% endif %} value="-1">Any</option>
{% for a in page_data.addr_types %} {% for a in page_data.addr_types %}
<option{% if filters.addr_type==a[0] %} selected{% endif %} value="{{ a[0] }}">{{ a[1] }}</option> <option{% if filters.addr_type==a[0] %} selected{% endif %} value="{{ a[0] }}">{{ a[1] }}</option>
{% endfor %} {% endfor %}
</select> </select>
</div>
</td> </td>
<td class="py-4 pr-5"></td> <td class="py-4 pr-5"></td>
</tr> </tr>
@@ -365,22 +407,50 @@
<div class="px-6"> <div class="px-6">
<div class="flex flex-wrap justify-end"> <div class="flex flex-wrap justify-end">
<div class="w-full md:w-auto p-1.5 ml-2"> <div class="w-full md:w-auto p-1.5 ml-2">
<button name="clearfilters" value="Clear Filters" class="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">Clear</button> <button name="clearfilters" value="Clear Filters" 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">
<svg class="mr-2 w-5 h-5" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
<line x1="20" y1="2" x2="12.329" y2="11.506"></line>
<path d="M11,11a2,2,0,0,1,2,2,3.659,3.659,0,0,1-.2.891A9.958,9.958,0,0,0,13.258,23H1C1,16.373,4.373,11,11,11Z"></path>
<line x1="18" y1="15" x2="23" y2="15" stroke="#ffffff"></line>
<line x1="17" y1="19" x2="23" y2="19" stroke="#ffffff"></line>
<line x1="19" y1="23" x2="23" y2="23" stroke="#ffffff"></line>
<path d="M8.059,11.415A3.9,3.9,0,0,0,12,16c.041,0,.079-.011.12-.012" data-cap="butt"></path>
<path d="M5,23a13.279,13.279,0,0,1,.208-3.4" data-cap="butt"></path>
<path d="M9.042,23c-.688-1.083-.313-3.4-.313-3.4" data-cap="butt"></path>
</g>
</svg>Clear</button>
</div> </div>
<div class="w-full md:w-auto p-1.5 ml-2"> <div class="w-full md:w-auto p-1.5 ml-2">
<button name="applyfilters" value="Submit" 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"> <button name="applyfilters" value="Submit" 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">
{{ filter_apply_svg | safe }} <svg class="mr-2 w-5 h-5" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
Apply Filters</button> <g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
<rect x="2" y="2" width="7" height="7"></rect>
<rect x="15" y="15" width="7" height="7"></rect>
<rect x="2" y="15" width="7" height="7"></rect>
<polyline points="15 6 17 8 22 3" stroke="#ffffff"></polyline>
</g>
</svg>Apply Filters</button>
</div> </div>
<div class="w-full md:w-auto p-1.5 ml-2"> <div class="w-full md:w-auto p-1.5 ml-2">
<button name="shownewaddr" value="New Address" 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"> <button name="shownewaddr" value="New Address" 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">
{{ circle_plus_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
New Address</button> <g stroke-linecap="square" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="miter" class="nc-icon-wrapper" stroke-miterlimit="10">
<line x1="12" y1="7" x2="12" y2="17" stroke="#ffffff"></line>
<line x1="17" y1="12" x2="7" y2="12" stroke="#ffffff"></line>
<circle cx="12" cy="12" r="11"></circle>
</g>
</svg>New Address</button>
</div> </div>
<div class="w-full md:w-auto p-1.5 ml-2"> <div class="w-full md:w-auto p-1.5 ml-2">
<button name="showaddaddr" value="Add Sending Address" 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"> <button name="showaddaddr" value="Add Sending Address" 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">
{{ circle_plus_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
Add Sending Address</button> <g stroke-linecap="square" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="miter" class="nc-icon-wrapper" stroke-miterlimit="10">
<line x1="12" y1="7" x2="12" y2="17" stroke="#ffffff"></line>
<line x1="17" y1="12" x2="7" y2="12" stroke="#ffffff"></line>
<circle cx="12" cy="12" r="11"></circle>
</g>
</svg>Add Sending Address</button>
</div> </div>
</div> </div>
</div> </div>
@@ -480,8 +550,10 @@
<div class="flex flex-wrap justify-end"> <div class="flex flex-wrap justify-end">
<div class="w-full md:w-auto p-1.5"> <div class="w-full md:w-auto p-1.5">
<button type="submit" name='pageback' value="Page Back" class="inline-flex items-center h-9 py-1 px-4 text-xs text-blue-50 font-semibold bg-blue-500 hover:bg-blue-600 rounded-lg transition duration-200 focus:ring-0 focus:outline-none"> <button type="submit" name='pageback' value="Page Back" class="inline-flex items-center h-9 py-1 px-4 text-xs text-blue-50 font-semibold bg-blue-500 hover:bg-blue-600 rounded-lg transition duration-200 focus:ring-0 focus:outline-none">
{{ page_back_svg| safe }} <svg aria-hidden="true" class="mr-2 w-5 h-5" fill="#ffffff" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<span>Previous</span> <path fill-rule="evenodd" d="M7.707 14.707a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 1.414L5.414 9H17a1 1 0 110 2H5.414l2.293 2.293a1 1 0 010 1.414z" clip-rule="evenodd"></path>
</svg>
<span>Page Back</span>
</button> </button>
</div> </div>
<div class="flex items-center"> <div class="flex items-center">
@@ -491,8 +563,10 @@
</div> </div>
<div class="w-full md:w-auto p-1.5"> <div class="w-full md:w-auto p-1.5">
<button type="submit" name='pageforwards' value="Page Forwards" class="inline-flex items-center h-9 py-1 px-4 text-xs text-blue-50 font-semibold bg-blue-500 hover:bg-blue-600 rounded-lg transition duration-200 focus:ring-0 focus:outline-none"> <button type="submit" name='pageforwards' value="Page Forwards" class="inline-flex items-center h-9 py-1 px-4 text-xs text-blue-50 font-semibold bg-blue-500 hover:bg-blue-600 rounded-lg transition duration-200 focus:ring-0 focus:outline-none">
<span>Next</span> <span>Page Forwards</span>
{{ page_forwards_svg| safe }} <svg aria-hidden="true" class="ml-2 w-5 h-5" fill="#ffffff" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M12.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-2.293-2.293a1 1 0 010-1.414z" clip-rule="evenodd"></path>
</svg>
</button> </button>
</div> </div>
</div> </div>

View File

@@ -1,79 +1,59 @@
{% set select_box_arrow_svg = ' {% set select_box_arrow_svg = '<svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path> <path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg> </svg>' %}
' %}
{% set circular_arrows_svg = ' {% set circular_arrows_svg = '<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g fill="#ffffff" class="nc-icon-wrapper"> <g fill="#ffffff" class="nc-icon-wrapper">
<path fill="#ffffff" d="M12,3c1.989,0,3.873,0.65,5.43,1.833l-3.604,3.393l9.167,0.983L22.562,0l-3.655,3.442C16.957,1.862,14.545,1,12,1C5.935,1,1,5.935,1,12h2C3,7.037,7.037,3,12,3z"></path> <path fill="#ffffff" d="M12,3c1.989,0,3.873,0.65,5.43,1.833l-3.604,3.393l9.167,0.983L22.562,0l-3.655,3.442C16.957,1.862,14.545,1,12,1C5.935,1,1,5.935,1,12h2C3,7.037,7.037,3,12,3z"></path>
<path data-color="color-2" d="M12,21c-1.989,0-3.873-0.65-5.43-1.833l3.604-3.393l-9.167-0.983L1.438,24l3.655-3.442C7.043,22.138,9.455,23,12,23c6.065,0,11-4.935,11-11h-2C21,16.963,16.963,21,12,21z"></path> <path data-color="color-2" d="M12,21c-1.989,0-3.873-0.65-5.43-1.833l3.604-3.393l-9.167-0.983L1.438,24l3.655-3.442C7.043,22.138,9.455,23,12,23c6.065,0,11-4.935,11-11h-2C21,16.963,16.963,21,12,21z"></path>
</g> </g>
</svg> </svg>' %}
' %}
{% set circular_error_svg = ' {% set circular_error_svg = '<svg class="relative top-0.5" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<svg class="relative top-0.5" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.4733 5.52667C10.4114 5.46419 10.3376 5.41459 10.2564 5.38075C10.1751 5.3469 10.088 5.32947 9.99999 5.32947C9.91198 5.32947 9.82485 5.3469 9.74361 5.38075C9.66237 5.41459 9.58863 5.46419 9.52666 5.52667L7.99999 7.06001L6.47333 5.52667C6.34779 5.40114 6.17753 5.33061 5.99999 5.33061C5.82246 5.33061 5.65219 5.40114 5.52666 5.52667C5.40112 5.65221 5.3306 5.82247 5.3306 6.00001C5.3306 6.17754 5.40112 6.3478 5.52666 6.47334L7.05999 8.00001L5.52666 9.52667C5.46417 9.58865 5.41458 9.66238 5.38073 9.74362C5.34689 9.82486 5.32946 9.912 5.32946 10C5.32946 10.088 5.34689 10.1752 5.38073 10.2564C5.41458 10.3376 5.46417 10.4114 5.52666 10.4733C5.58863 10.5358 5.66237 10.5854 5.74361 10.6193C5.82485 10.6531 5.91198 10.6705 5.99999 10.6705C6.088 10.6705 6.17514 10.6531 6.25638 10.6193C6.33762 10.5854 6.41135 10.5358 6.47333 10.4733L7.99999 8.94001L9.52666 10.4733C9.58863 10.5358 9.66237 10.5854 9.74361 10.6193C9.82485 10.6531 9.91198 10.6705 9.99999 10.6705C10.088 10.6705 10.1751 10.6531 10.2564 10.6193C10.3376 10.5854 10.4114 10.5358 10.4733 10.4733C10.5358 10.4114 10.5854 10.3376 10.6193 10.2564C10.6531 10.1752 10.6705 10.088 10.6705 10C10.6705 9.912 10.6531 9.82486 10.6193 9.74362C10.5854 9.66238 10.5358 9.58865 10.4733 9.52667L8.93999 8.00001L10.4733 6.47334C10.5358 6.41137 10.5854 6.33763 10.6193 6.25639C10.6531 6.17515 10.6705 6.08802 10.6705 6.00001C10.6705 5.912 10.6531 5.82486 10.6193 5.74362C10.5854 5.66238 10.5358 5.58865 10.4733 5.52667ZM12.7133 3.28667C12.0983 2.64994 11.3627 2.14206 10.5494 1.79266C9.736 1.44327 8.8612 1.25936 7.976 1.25167C7.0908 1.24398 6.21294 1.41266 5.39363 1.74786C4.57432 2.08307 3.82998 2.57809 3.20403 3.20404C2.57807 3.82999 2.08305 4.57434 1.74785 5.39365C1.41264 6.21296 1.24396 7.09082 1.25166 7.97602C1.25935 8.86121 1.44326 9.73601 1.79265 10.5494C2.14204 11.3627 2.64992 12.0984 3.28666 12.7133C3.90164 13.3501 4.63727 13.858 5.45063 14.2074C6.26399 14.5567 7.13879 14.7407 8.02398 14.7483C8.90918 14.756 9.78704 14.5874 10.6064 14.2522C11.4257 13.9169 12.17 13.4219 12.796 12.796C13.4219 12.17 13.9169 11.4257 14.2521 10.6064C14.5873 9.78706 14.756 8.90919 14.7483 8.024C14.7406 7.1388 14.5567 6.264 14.2073 5.45064C13.8579 4.63728 13.3501 3.90165 12.7133 3.28667ZM11.7733 11.7733C10.9014 12.6463 9.75368 13.1899 8.52585 13.3115C7.29802 13.4332 6.066 13.1254 5.03967 12.4405C4.01335 11.7557 3.25623 10.7361 2.89731 9.55566C2.53838 8.37518 2.59986 7.10677 3.07127 5.96653C3.54267 4.82629 4.39484 3.88477 5.48259 3.30238C6.57033 2.71999 7.82635 2.53276 9.03666 2.77259C10.247 3.01242 11.3367 3.66447 12.1202 4.61765C12.9036 5.57083 13.3324 6.76617 13.3333 8.00001C13.3357 8.70087 13.1991 9.39524 12.9313 10.0429C12.6635 10.6906 12.2699 11.2788 11.7733 11.7733Z" fill="#EF5944"></path> <path d="M10.4733 5.52667C10.4114 5.46419 10.3376 5.41459 10.2564 5.38075C10.1751 5.3469 10.088 5.32947 9.99999 5.32947C9.91198 5.32947 9.82485 5.3469 9.74361 5.38075C9.66237 5.41459 9.58863 5.46419 9.52666 5.52667L7.99999 7.06001L6.47333 5.52667C6.34779 5.40114 6.17753 5.33061 5.99999 5.33061C5.82246 5.33061 5.65219 5.40114 5.52666 5.52667C5.40112 5.65221 5.3306 5.82247 5.3306 6.00001C5.3306 6.17754 5.40112 6.3478 5.52666 6.47334L7.05999 8.00001L5.52666 9.52667C5.46417 9.58865 5.41458 9.66238 5.38073 9.74362C5.34689 9.82486 5.32946 9.912 5.32946 10C5.32946 10.088 5.34689 10.1752 5.38073 10.2564C5.41458 10.3376 5.46417 10.4114 5.52666 10.4733C5.58863 10.5358 5.66237 10.5854 5.74361 10.6193C5.82485 10.6531 5.91198 10.6705 5.99999 10.6705C6.088 10.6705 6.17514 10.6531 6.25638 10.6193C6.33762 10.5854 6.41135 10.5358 6.47333 10.4733L7.99999 8.94001L9.52666 10.4733C9.58863 10.5358 9.66237 10.5854 9.74361 10.6193C9.82485 10.6531 9.91198 10.6705 9.99999 10.6705C10.088 10.6705 10.1751 10.6531 10.2564 10.6193C10.3376 10.5854 10.4114 10.5358 10.4733 10.4733C10.5358 10.4114 10.5854 10.3376 10.6193 10.2564C10.6531 10.1752 10.6705 10.088 10.6705 10C10.6705 9.912 10.6531 9.82486 10.6193 9.74362C10.5854 9.66238 10.5358 9.58865 10.4733 9.52667L8.93999 8.00001L10.4733 6.47334C10.5358 6.41137 10.5854 6.33763 10.6193 6.25639C10.6531 6.17515 10.6705 6.08802 10.6705 6.00001C10.6705 5.912 10.6531 5.82486 10.6193 5.74362C10.5854 5.66238 10.5358 5.58865 10.4733 5.52667ZM12.7133 3.28667C12.0983 2.64994 11.3627 2.14206 10.5494 1.79266C9.736 1.44327 8.8612 1.25936 7.976 1.25167C7.0908 1.24398 6.21294 1.41266 5.39363 1.74786C4.57432 2.08307 3.82998 2.57809 3.20403 3.20404C2.57807 3.82999 2.08305 4.57434 1.74785 5.39365C1.41264 6.21296 1.24396 7.09082 1.25166 7.97602C1.25935 8.86121 1.44326 9.73601 1.79265 10.5494C2.14204 11.3627 2.64992 12.0984 3.28666 12.7133C3.90164 13.3501 4.63727 13.858 5.45063 14.2074C6.26399 14.5567 7.13879 14.7407 8.02398 14.7483C8.90918 14.756 9.78704 14.5874 10.6064 14.2522C11.4257 13.9169 12.17 13.4219 12.796 12.796C13.4219 12.17 13.9169 11.4257 14.2521 10.6064C14.5873 9.78706 14.756 8.90919 14.7483 8.024C14.7406 7.1388 14.5567 6.264 14.2073 5.45064C13.8579 4.63728 13.3501 3.90165 12.7133 3.28667ZM11.7733 11.7733C10.9014 12.6463 9.75368 13.1899 8.52585 13.3115C7.29802 13.4332 6.066 13.1254 5.03967 12.4405C4.01335 11.7557 3.25623 10.7361 2.89731 9.55566C2.53838 8.37518 2.59986 7.10677 3.07127 5.96653C3.54267 4.82629 4.39484 3.88477 5.48259 3.30238C6.57033 2.71999 7.82635 2.53276 9.03666 2.77259C10.247 3.01242 11.3367 3.66447 12.1202 4.61765C12.9036 5.57083 13.3324 6.76617 13.3333 8.00001C13.3357 8.70087 13.1991 9.39524 12.9313 10.0429C12.6635 10.6906 12.2699 11.2788 11.7733 11.7733Z" fill="#EF5944"></path>
</svg> </svg>' %}
' %}
{% set circular_info_svg = ' {% set circular_info_svg = '<svg aria-hidden="true" class="flex-shrink-0 w-5 h-5 text-blue-700 dark:text-blue-800" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<svg aria-hidden="true" class="flex-shrink-0 w-5 h-5 text-blue-700 dark:text-blue-800" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"></path> <path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"></path>
</svg> </svg>' %}
' %}
{% set cross_close_svg = ' {% set cross_close_svg = '<svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path> <path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
</svg> </svg>' %}
' %}
{% set breadcrumb_line_svg = ' {% set breadcrumb_line_svg = '<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path></svg>' %}
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path> {% set withdraw_svg = '<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24"><g fill="#ffffff" class="nc-icon-wrapper"><polygon data-color="color-2" points="6,10 12,17 18,10 13,10 13,1 11,1 11,10 "></polygon><path fill="#ffffff" d="M22,21H2v-6H0v7c0,0.552,0.448,1,1,1h22c0.552,0,1-0.448,1-1v-7h-2V21z"></path></g></svg>' %}
</svg>
' %} {% set utxo_groups_svg = '<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
{% set withdraw_svg = '
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g fill="#ffffff" class="nc-icon-wrapper">
<polygon data-color="color-2" points="6,10 12,17 18,10 13,10 13,1 11,1 11,10 "></polygon>
<path fill="#ffffff" d="M22,21H2v-6H0v7c0,0.552,0.448,1,1,1h22c0.552,0,1-0.448,1-1v-7h-2V21z"></path>
</g>
</svg>
' %}
{% set utxo_groups_svg = '
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round" class="nc-icon-wrapper"> <g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round" class="nc-icon-wrapper">
<rect x="2" y="9" width="12" height="14"></rect> <rect x="2" y="9" width="12" height="14"></rect>
<polyline points=" 6,5 18,5 18,19 " stroke="#ffffff"></polyline> <polyline points=" 6,5 18,5 18,19 " stroke="#ffffff"></polyline>
<polyline points=" 10,1 22,1 22,15 " stroke="#ffffff"></polyline> <polyline points=" 10,1 22,1 22,15 " stroke="#ffffff"></polyline>
</g> </g>
</svg> </svg>' %}
' %}
{% set create_utxo_svg = ' {% set create_utxo_svg = '<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round" class="nc-icon-wrapper"> <g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round" class="nc-icon-wrapper">
<polyline points="1 15 1 21 23 21 23 15"></polyline> <polyline points="1 15 1 21 23 21 23 15"></polyline>
<line x1="12" y1="3" x2="12" y2="13" stroke="#ffffff"></line> <line x1="12" y1="3" x2="12" y2="13" stroke="#ffffff"></line>
<line x1="17" y1="8" x2="7" y2="8" stroke="#ffffff"></line> <line x1="17" y1="8" x2="7" y2="8" stroke="#ffffff"></line>
</g> </g>
</svg>' %}
{% set lock_svg = '<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g fill="#ffffff"><path d="M19,10H5a3,3,0,0,0-3,3v8a3,3,0,0,0,3,3H19a3,3,0,0,0,3-3V13A3,3,0,0,0,19,10Zm-7,9a2,2,0,1,1,2-2A2,2,0,0,1,12,19Z" fill="#ffffff"></path><path data-color="color-2" d="M18,8H16V6a3.958,3.958,0,0,0-3.911-4h-.042A3.978,3.978,0,0,0,8,5.911V8H6V5.9A5.961,5.961,0,0,1,11.949,0h.061A5.979,5.979,0,0,1,18,6.01Z"></path></g>
</svg> </svg>
' %} ' %}
{% set lock_svg = '
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24"> {% set eye_show_svg = '<svg xmlns="http://www.w3.org/2000/svg" fill="#ffffff" height="20" width="20" viewBox="0 0 24 24">
<g fill="#ffffff">
<path d="M19,10H5a3,3,0,0,0-3,3v8a3,3,0,0,0,3,3H19a3,3,0,0,0,3-3V13A3,3,0,0,0,19,10Zm-7,9a2,2,0,1,1,2-2A2,2,0,0,1,12,19Z" fill="#ffffff"></path>
<path data-color="color-2" d="M18,8H16V6a3.958,3.958,0,0,0-3.911-4h-.042A3.978,3.978,0,0,0,8,5.911V8H6V5.9A5.961,5.961,0,0,1,11.949,0h.061A5.979,5.979,0,0,1,18,6.01Z"></path>
</g>
</svg>
' %}
{% set eye_show_svg = '
<svg xmlns="http://www.w3.org/2000/svg" fill="#ffffff" height="20" width="20" viewBox="0 0 24 24">
<path d="M23.444,10.239a22.936,22.936,0,0,0-2.492-2.948l-4.021,4.021A5.026,5.026,0,0,1,17,12a5,5,0,0,1-5,5,5.026,5.026,0,0,1-.688-.069L8.055,20.188A10.286,10.286,0,0,0,12,21c5.708,0,9.905-5.062,11.445-7.24A3.058,3.058,0,0,0,23.444,10.239Z"></path> <path d="M23.444,10.239a22.936,22.936,0,0,0-2.492-2.948l-4.021,4.021A5.026,5.026,0,0,1,17,12a5,5,0,0,1-5,5,5.026,5.026,0,0,1-.688-.069L8.055,20.188A10.286,10.286,0,0,0,12,21c5.708,0,9.905-5.062,11.445-7.24A3.058,3.058,0,0,0,23.444,10.239Z"></path>
<path d="M12,3C6.292,3,2.1,8.062,.555,10.24a3.058,3.058,0,0,0,0,3.52h0a21.272,21.272,0,0,0,4.784,4.9l3.124-3.124a5,5,0,0,1,7.071-7.072L8.464,15.536l10.2-10.2A11.484,11.484,0,0,0,12,3Z"></path> <path d="M12,3C6.292,3,2.1,8.062,.555,10.24a3.058,3.058,0,0,0,0,3.52h0a21.272,21.272,0,0,0,4.784,4.9l3.124-3.124a5,5,0,0,1,7.071-7.072L8.464,15.536l10.2-10.2A11.484,11.484,0,0,0,12,3Z"></path>
<path data-color="color-2" d="M1,24a1,1,0,0,1-.707-1.707l22-22a1,1,0,0,1,1.414,1.414l-22,22A1,1,0,0,1,1,24Z"></path> <path data-color="color-2" d="M1,24a1,1,0,0,1-.707-1.707l22-22a1,1,0,0,1,1.414,1.414l-22,22A1,1,0,0,1,1,24Z"></path>
</svg> </svg>
' %} ' %}
{% set place_new_offer_svg = '
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 24 24"> {% set place_new_offer_svg = '<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round"> <g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
<circle cx="5" cy="5" r="4"></circle> <circle cx="5" cy="5" r="4"></circle>
<circle cx="19" cy="19" r="4"></circle> <circle cx="19" cy="19" r="4"></circle>
@@ -82,20 +62,21 @@
<polyline points=" 16,2 13,5 16,8 " stroke="#ffffff"></polyline> <polyline points=" 16,2 13,5 16,8 " stroke="#ffffff"></polyline>
<polyline points=" 8,16 11,19 8,22 " stroke="#ffffff"></polyline> <polyline points=" 8,16 11,19 8,22 " stroke="#ffffff"></polyline>
</g> </g>
</svg> </svg>
' %} ' %}
{% set page_back_svg = '
<svg aria-hidden="true" class="mr-2 w-5 h-5" fill="#fff" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> {% set page_back_svg = '<svg aria-hidden="true" class="mr-2 w-5 h-5" fill="#fff" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M7.707 14.707a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 1.414L5.414 9H17a1 1 0 110 2H5.414l2.293 2.293a1 1 0 010 1.414z" clip-rule="evenodd"></path> <path fill-rule="evenodd" d="M7.707 14.707a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 1.414L5.414 9H17a1 1 0 110 2H5.414l2.293 2.293a1 1 0 010 1.414z" clip-rule="evenodd"></path>
</svg> </svg>
' %} ' %}
{% set page_forwards_svg = '
<svg aria-hidden="true" class="ml-2 w-5 h-5" fill="#fff" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> {% set page_forwards_svg = '<svg aria-hidden="true" class="ml-2 w-5 h-5" fill="#fff" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M12.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-2.293-2.293a1 1 0 010-1.414z" clip-rule="evenodd"></path> <path fill-rule="evenodd" d="M12.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-2.293-2.293a1 1 0 010-1.414z" clip-rule="evenodd"></path>
</svg> </svg>
' %} ' %}
{% set filter_clear_svg = '
<svg class="mr-2 w-5 h-5" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
{% set filter_clear_svg = '<svg class="mr-2 w-5 h-5" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round"> <g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
<line x1="20" y1="2" x2="12.329" y2="11.506"></line> <line x1="20" y1="2" x2="12.329" y2="11.506"></line>
<path d="M11,11a2,2,0,0,1,2,2,3.659,3.659,0,0,1-.2.891A9.958,9.958,0,0,0,13.258,23H1C1,16.373,4.373,11,11,11Z"></path> <path d="M11,11a2,2,0,0,1,2,2,3.659,3.659,0,0,1-.2.891A9.958,9.958,0,0,0,13.258,23H1C1,16.373,4.373,11,11,11Z"></path>
@@ -106,592 +87,32 @@
<path d="M5,23a13.279,13.279,0,0,1,.208-3.4" data-cap="butt"></path> <path d="M5,23a13.279,13.279,0,0,1,.208-3.4" data-cap="butt"></path>
<path d="M9.042,23c-.688-1.083-.313-3.4-.313-3.4" data-cap="butt"></path> <path d="M9.042,23c-.688-1.083-.313-3.4-.313-3.4" data-cap="butt"></path>
</g> </g>
</svg> </svg>
' %} ' %}
{% set filter_apply_svg = '
<svg class="mr-2 w-5 h-5" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24"> {% set filter_apply_svg = ' <svg class="mr-2 w-5 h-5" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round"> <g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
<rect x="2" y="2" width="7" height="7"></rect> <rect x="2" y="2" width="7" height="7"></rect>
<rect x="15" y="15" width="7" height="7"></rect> <rect x="15" y="15" width="7" height="7"></rect>
<rect x="2" y="15" width="7" height="7"></rect> <rect x="2" y="15" width="7" height="7"></rect>
<polyline points="15 6 17 8 22 3" stroke="#ffffff"></polyline> <polyline points="15 6 17 8 22 3" stroke="#ffffff"></polyline>
</g> </g>
</svg> </svg>
' %} ' %}
{% set input_arrow_down_svg = '
<svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
{% set input_arrow_down_svg = '<svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path> <path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg> </svg>
' %} ' %}
{% set arrow_right_svg = '
<svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg "> {% set arrow_right_svg = ' <svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg ">
<path fill-rule="evenodd " d="M12.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-2.293-2.293a1 1 0 010-1.414z " clip-rule="evenodd"></path> <path fill-rule="evenodd " d="M12.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-2.293-2.293a1 1 0 010-1.414z " clip-rule="evenodd"></path>
</svg> </svg>
' %}
{% set wallet_svg = '
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<path d="M6,3H3C1.895,3,1,3.895,1,5 v0c0,1.105,0.895,2,2,2"></path>
<polyline points=" 6,7 6,1 20,1 20,7 " stroke="#6b7280"></polyline>
<path d="M23,7H3 C1.895,7,1,6.105,1,5v15c0,1.657,1.343,3,3,3h19V7z"></path>
<circle cx="17" cy="15" r="2"></circle>
</g>
</svg>
' %}
{% set order_book_svg = '
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<rect x="3" y="1" width="18" height="22"></rect>
<line x1="12" y1="8" x2="12" y2="16" stroke="#6b7280"></line>
<line x1="8" y1="14" x2="8" y2="16" stroke="#6b7280"></line>
<line x1="16" y1="11" x2="16" y2="16" stroke="#6b7280"> </line>
</g>
</svg>
' %}
{% set new_offer_svg = '
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
<circle cx="5" cy="5" r="4"></circle>
<circle cx="19" cy="19" r="4"></circle>
<polyline data-cap="butt" points="13,5 21,5 21,11 " stroke="#ffffff"></polyline>
<polyline data-cap="butt" points="11,19 3,19 3,13 " stroke="#ffffff"></polyline>
<polyline points=" 16,2 13,5 16,8 " stroke="#ffffff"></polyline>
<polyline points=" 8,16 11,19 8,22 " stroke="#ffffff"></polyline>
</g>
</svg>
' %}
{% set settings_svg = '
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<path d="M14,19l2.95,2.95A3.5,3.5,0,0,0,21.9,22l.051-.051h0A3.5,3.5,0,0,0,22,17l-.051-.051L20,15" stroke="#6b7280"></path>
<polyline data-cap="butt" points="11.491 8.866 4.203 1.578 1.661 4.12 8.779 11.238" stroke="#6b7280"></polyline>
<path d="M22.678,4.922,19.6,7.987l-3.6-3.576,3.08-3.066a4.214,4.214,0,0,0-2.259-.307,5.615,5.615,0,0,0-5.133,5.723A4.223,4.223,0,0,0,12,8.4L2.145,17.083a3.419,3.419,0,0,0-.276,4.827c.023.027.047.052.071.078h0a3.286,3.286,0,0,0,4.647.1,3.232,3.232,0,0,0,.281-.3l8.726-9.81a6.717,6.717,0,0,0,2.875.2A5.687,5.687,0,0,0,22.78,8.192,5.088,5.088,0,0,0,22.678,4.922Z"></path>
</g>
</svg>
' %}
{% set cog_svg = '
<svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<circle cx="12" cy="12" r="3" stroke="#6b7280"></circle>
<path d="M20,12a8.049,8.049,0,0,0-.188-1.713l2.714-2.055-2-3.464L17.383,6.094a7.987,7.987,0,0,0-2.961-1.719L14,1H10L9.578,4.375A7.987,7.987,0,0,0,6.617,6.094L3.474,4.768l-2,3.464,2.714,2.055a7.9,7.9,0,0,0,0,3.426L1.474,15.768l2,3.464,3.143-1.326a7.987,7.987,0,0,0,2.961,1.719L10,23h4l.422-3.375a7.987,7.987,0,0,0,2.961-1.719l3.143,1.326,2-3.464-2.714-2.055A8.049,8.049,0,0,0,20,12Z"></path>
</g>
</svg>
' %}
{% set rpc_svg = '
<svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<rect x="1" y="2" width="22" height="20"></rect>
<line x1="1" y1="6" x2="23" y2="6"></line>
<polyline points=" 5,11 7,13 5,15 " stroke="#6b7280"></polyline>
<line x1="10" y1="15" x2="14" y2="15" stroke="#6b7280"></line>
<line x1="6" y1="2" x2="6" y2="6"></line>
</g>
</svg>
' %}
{% set debug_svg = '
<svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<path data-cap="butt" d="M5.29,10H4A3,3,0,0,1,1,7V6" stroke="#6b7280"></path>
<path data-cap="butt" d="M5.29,18H4a3,3,0,0,0-3,3v1" stroke="#6b7280"></path>
<path data-cap="butt" d="M8,6.255V5a4,4,0,0,1,4-4h0a4,4,0,0,1,4,4V6.255" stroke="#6b7280"></path>
<line x1="5" y1="14" x2="1" y2="14" stroke="#6b7280"></line>
<path data-cap="butt" d="M18.71,10H20a3,3,0,0,0,3-3V6" stroke="#6b7280"></path>
<path data-cap="butt" d="M18.71,18H20a3,3,0,0,1,3,3v1" stroke="#6b7280"></path>
<line x1="19" y1="14" x2="23" y2="14" stroke="#6b7280"></line>
<path d="M19,16A7,7,0,0,1,5,16V12a7,7,0,0,1,14,0Z"></path>
</g>
</svg>
' %}
{% set explorer_svg = '
<svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<line x1="22" y1="22" x2="15.656" y2="15.656" stroke="#6b7280"></line>
<circle cx="10" cy="10" r="8"></circle>
</g>
</svg>
' %}
{% set tor_svg = '
<svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<path d="M9,18.8A6.455,6.455,0,0,1,7,14,6.455,6.455,0,0,1,9,9.2" stroke="#6b7280"></path>
<path d="M15,18.8A6.455,6.455,0,0,0,17,14a6.455,6.455,0,0,0-2-4.8" stroke="#6b7280"></path>
<path d="M14,2.256V1H10V2.256A3.949,3.949,0,0,1,7.658,5.891,8.979,8.979,0,0,0,2,14c0,4.971,4.477,9,10,9s10-4.029,10-9a8.978,8.978,0,0,0-5.658-8.109A3.95,3.95,0,0,1,14,2.256Z"></path>
</g>
</svg>
' %}
{% set tor_purple_svg = '
<svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#AA70E4" stroke-linejoin="round">
<path d="M9,18.8A6.455,6.455,0,0,1,7,14,6.455,6.455,0,0,1,9,9.2" stroke="#AA70E4"></path>
<path d="M15,18.8A6.455,6.455,0,0,0,17,14a6.455,6.455,0,0,0-2-4.8" stroke="#AA70E4"></path>
<path d="M14,2.256V1H10V2.256A3.949,3.949,0,0,1,7.658,5.891,8.979,8.979,0,0,0,2,14c0,4.971,4.477,9,10,9s10-4.029,10-9a8.978,8.978,0,0,0-5.658-8.109A3.95,3.95,0,0,1,14,2.256Z"></path>
</g>
</svg>
' %}
{% set smsg_svg = '
<svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<path data-cap="butt" d="M11.992,11.737,14.2,13.4A2,2,0,0,1,15,15v1H7V15a2,2,0,0,1,.8-1.6l2.208-1.663" stroke="#6b7280"></path>
<rect x="9" y="7" width="4" height="5" rx="2" ry="2" stroke="#6b7280"></rect>
<path d="M2,1H18a2,2,0,0,1,2,2V21a2,2,0,0,1-2,2H2Z"></path>
<line x1="23" y1="5" x2="23" y2="9" stroke="#6b7280"></line>
</g>
</svg>
' %}
{% set outputs_svg = '
<svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<path d="M1.373,13.183a2.064,2.064,0,0,1,0-2.366C2.946,8.59,6.819,4,12,4s9.054,4.59,10.627,6.817a2.064,2.064,0,0,1,0,2.366C21.054,15.41,17.181,20,12,20S2.946,15.41,1.373,13.183Z"></path>
<circle cx="12" cy="12" r="4" stroke="#6b7280"></circle>
</g>
</svg>
' %}
{% set automation_svg = '
<svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<line data-cap="butt" x1="5" y1="1" x2="5" y2="6" stroke="#6b7280"></line>
<line x1="3" y1="1" x2="7" y2="1" stroke="#6b7280"> </line>
<line data-cap="butt" x1="19" y1="1" x2="19" y2="6" stroke="#6b7280"></line>
<line x1="17" y1="1" x2="21" y2="1" stroke="#6b7280"></line>
<rect x="6" y="15" width="12" height="4" stroke="#6b7280"></rect>
<line data-cap="butt" x1="10" y1="19" x2="10" y2="15" stroke="#6b7280"></line>
<line data-cap="butt" x1="14" y1="19" x2="14" y2="15" stroke="#6b7280"></line>
<line x1="6" y1="11" x2="8" y2="11" stroke="#6b7280"></line>
<line x1="16" y1="11" x2="18" y2="11" stroke="#6b7280"> </line>
<polygon points="23 6 5 6 1 6 1 23 23 23 23 6"></polygon>
</g>
</svg>
' %}
{% set shutdown_svg = '
<svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<line data-cap="butt" x1="11" y1="10" x2="22" y2="10" stroke="#6b7280"></line>
<polyline points="18 6 22 10 18 14" stroke="#6b7280"></polyline>
<polyline data-cap="butt" points="13 13 13 17 8 17"></polyline>
<polyline data-cap="butt" points="1 2 8 7.016 8 22 1 17 1 2 13 2 13 7"></polyline>
</g>
</svg>
' %}
{% set notifications_svg = '
<svg class="h-5 w-5" viewBox="0 0 16 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14 11.18V8C13.9986 6.58312 13.4958 5.21247 12.5806 4.13077C11.6655 3.04908 10.3971 2.32615 9 2.09V1C9 0.734784 8.89464 0.48043 8.70711 0.292893C8.51957 0.105357 8.26522 0 8 0C7.73478 0 7.48043 0.105357 7.29289 0.292893C7.10536 0.48043 7 0.734784 7 1V2.09C5.60294 2.32615 4.33452 3.04908 3.41939 4.13077C2.50425 5.21247 2.00144 6.58312 2 8V11.18C1.41645 11.3863 0.910998 11.7681 0.552938 12.2729C0.194879 12.7778 0.00173951 13.3811 0 14V16C0 16.2652 0.105357 16.5196 0.292893 16.7071C0.48043 16.8946 0.734784 17 1 17H4.14C4.37028 17.8474 4.873 18.5954 5.5706 19.1287C6.26819 19.6621 7.1219 19.951 8 19.951C8.8781 19.951 9.73181 19.6621 10.4294 19.1287C11.127 18.5954 11.6297 17.8474 11.86 17H15C15.2652 17 15.5196 16.8946 15.7071 16.7071C15.8946 16.5196 16 16.2652 16 16V14C15.9983 13.3811 15.8051 12.7778 15.4471 12.2729C15.089 11.7681 14.5835 11.3863 14 11.18ZM4 8C4 6.93913 4.42143 5.92172 5.17157 5.17157C5.92172 4.42143 6.93913 4 8 4C9.06087 4 10.0783 4.42143 10.8284 5.17157C11.5786 5.92172 12 6.93913 12 8V11H4V8ZM8 18C7.65097 17.9979 7.30857 17.9045 7.00683 17.7291C6.70509 17.5536 6.45451 17.3023 6.28 17H9.72C9.54549 17.3023 9.29491 17.5536 8.99317 17.7291C8.69143 17.9045 8.34903 17.9979 8 18ZM14 15H2V14C2 13.7348 2.10536 13.4804 2.29289 13.2929C2.48043 13.1054 2.73478 13 3 13H13C13.2652 13 13.5196 13.1054 13.7071 13.2929C13.8946 13.4804 14 13.7348 14 14V15Z" fill="#6b7280"></path>
</svg>
' %}
{% set debug_nerd_svg = '
<svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#2ad167" stroke-linejoin="round">
<circle cx="12" cy="12" r="11"></circle>
<path data-cap="butt" d="M9,16a3,3,0,0,0,6,0" stroke="#2ad167"></path>
<circle cx="17" cy="10" r="3" stroke="#2ad167"></circle>
<circle cx="7" cy="10" r="3" stroke="#2ad167"></circle>
<path data-cap="butt" d="M10,10a2,2,0,0,1,4,0" stroke="#2ad167"></path>
</g>
</svg>
' %}
{% set wallet_unlocked_svg = '
<svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#f80b0b" stroke-linejoin="round">
<rect x="3" y="11" width="18" height="12"></rect>
<circle cx="12" cy="17" r="2" stroke="#f80b0b"></circle>
<path data-cap="butt" d="M17,6a4.951,4.951,0,0,0-4.9-5H12A4.951,4.951,0,0,0,7,5.9V11"></path>
</g>
</svg>
' %}
{% set wallet_locked_svg = '
<svg class="text-gray-500 w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#2ad167" stroke-linejoin="round">
<rect x="3" y="11" width="18" height="12" rx="2"></rect>
<circle cx="12" cy="17" r="2" stroke="#2ad167"></circle>
<path d="M17,7V6a4.951,4.951,0,0,0-4.9-5H12A4.951,4.951,0,0,0,7,5.9V7" stroke="#2ad167"></path>
</g>
</svg>
' %}
{% set moon_svg = '
<svg id="theme-toggle-dark-icon" class="hidden w-5 h-5" fill="#F59E0B" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"></path>
</svg>
' %}
{% set sun_svg = '
<svg id="theme-toggle-light-icon" class="hidden w-5 h-5" fill="#F59E0B" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z" fill-rule="evenodd" clip-rule="evenodd"></path>
</svg>
' %}
{% set swap_in_progress_svg = '
<svg class="text-gray-100 w-5 h-5 ml-7 mr-2" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<circle data-cap="butt" cx="12" cy="12" r="3" stroke="#6b7280"></circle>
<polyline points="16.071 5.341 21.763 6.927 21.034 1.13"></polyline>
<path data-cap="butt" d="M1,12A11,11,0,0,1,21.763,6.927"></path>
<polyline points="7.929 18.659 2.237 17.073 2.966 22.87"></polyline>
<path data-cap="butt" d="M23,12A11,11,0,0,1,2.237,17.073"></path>
</g>
</svg>
' %}
{% set swap_in_progress_svg = '
<svg class="text-gray-100 w-5 h-5 " xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<circle data-cap="butt" cx="12" cy="12" r="3" stroke="#6b7280"></circle>
<polyline points="16.071 5.341 21.763 6.927 21.034 1.13"></polyline>
<path data-cap="butt" d="M1,12A11,11,0,0,1,21.763,6.927"></path>
<polyline points="7.929 18.659 2.237 17.073 2.966 22.87"></polyline>
<path data-cap="butt" d="M23,12A11,11,0,0,1,2.237,17.073"></path>
</g>
</svg>
' %}
{% set swap_in_progress_green_svg = '
<svg class="text-gray-100 w-5 h-5 " xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#66CD73" stroke-linejoin="round">
<circle data-cap="butt" cx="12" cy="12" r="3" stroke="#66CD73"></circle>
<polyline points="16.071 5.341 21.763 6.927 21.034 1.13"></polyline>
<path data-cap="butt" d="M1,12A11,11,0,0,1,21.763,6.927"></path>
<polyline points="7.929 18.659 2.237 17.073 2.966 22.87"></polyline>
<path data-cap="butt" d="M23,12A11,11,0,0,1,2.237,17.073"></path>
</g>
</svg>
' %}
{% set swap_in_progress_mobile_svg = '
<svg class="text-gray-100 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<circle data-cap="butt" cx="12" cy="12" r="3" stroke="#6b7280"></circle>
<polyline points="16.071 5.341 21.763 6.927 21.034 1.13"></polyline>
<path data-cap="butt" d="M1,12A11,11,0,0,1,21.763,6.927"></path>
<polyline points="7.929 18.659 2.237 17.073 2.966 22.87"></polyline>
<path data-cap="butt" d="M23,12A11,11,0,0,1,2.237,17.073"></path>
</g>
</svg>
' %}
{% set your_offers_svg = '
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<circle cx="5" cy="5" r="4"></circle>
<circle cx="19" cy="19" r="4"></circle>
<polyline data-cap="butt" points="13,5 21,5 21,11 " stroke="#6b7280"></polyline>
<polyline data-cap="butt" points="11,19 3,19 3,13 " stroke="#6b7280"></polyline>
<polyline points=" 16,2 13,5 16,8 " stroke="#6b7280"></polyline>
<polyline points=" 8,16 11,19 8,22 " stroke="#6b7280"></polyline>
</g>
</svg>
' %}
{% set available_bids_svg = '
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<circle cx="12" cy="12" r="11"></circle>
<polyline points=" 12,6 12,12 18,12 " stroke="#6b7280"></polyline>
</g>
</svg>
' %}
{% set bids_received_svg = '
<svg class="text-gray-100 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<path d="M2,16v4a2,2,0,0,0,2,2H20a2,2,0,0,0,2-2V16"> </path>
<line data-cap="butt" x1="12" y1="1" x2="12" y2="16" stroke="#6b7280"></line>
<polyline points="7 11 12 16 17 11" stroke="#6b7280"></polyline>
</g>
</svg>
' %}
{% set bids_sent_svg = '
<svg class="text-gray-100 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#6b7280" stroke-linejoin="round">
<path d="M2,16v4a2,2,0,0,0,2,2H20a2,2,0,0,0,2-2V16"></path>
<line data-cap="butt" x1="12" y1="17" x2="12" y2="2" stroke="#6b7280"></line>
<polyline points="17 7 12 2 7 7" stroke="#6b7280"></polyline>
</g>
</svg>
' %}
{% set mobile_menu_svg = '
<svg class="text-white bg-blue-500 hover:bg-blue-600 block h-8 w-8 p-2 rounded" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" fill="currentColor">
<title>Mobile Menu</title>
<path d="M0 3h20v2H0V3zm0 6h20v2H0V9zm0 6h20v2H0v-2z"></path>
</svg>
' %}
{% set header_arrow_down_svg = '
<svg class="text-gray-400 ml-4" width="10" height="6" viewBox="0 0 10 6" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.08335 0.666657C8.75002 0.333323 8.25002 0.333323 7.91669 0.666657L5.00002 3.58332L2.08335 0.666657C1.75002 0.333323 1.25002 0.333323 0.916687 0.666657C0.583354 0.99999 0.583354 1.49999 0.916687 1.83332L4.41669 5.33332C4.58335 5.49999 4.75002 5.58332 5.00002 5.58332C5.25002 5.58332 5.41669 5.49999 5.58335 5.33332L9.08335 1.83332C9.41669 1.49999 9.41669 0.99999 9.08335 0.666657Z" fill="#6b7280"></path>
</svg>
' %}
{% set notifications_network_offer_svg = '
<svg class="w-5 h-5" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
<circle cx="5" cy="5" r="4"></circle>
<circle cx="19" cy="19" r="4"></circle>
<polyline data-cap="butt" points="13,5 21,5 21,11 " stroke="#ffffff"></polyline>
<polyline data-cap="butt" points="11,19 3,19 3,13 " stroke="#ffffff"></polyline>
<polyline points=" 16,2 13,5 16,8 " stroke="#ffffff"></polyline>
<polyline points=" 8,16 11,19 8,22 " stroke="#ffffff"></polyline>
</g>
</svg>
' %}
{% set notifications_new_bid_on_offer_svg = '
<svg class="w-5 h-5" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
<rect x="9.843" y="5.379" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -0.7635 13.1569)" width="11.314" height="4.243"></rect>
<polyline points="3,23 3,19 15,19 15,23 "></polyline>
<line x1="4" y1="15" x2="1" y2="15" stroke="#ffffff"></line>
<line x1="5.757" y1="10.757" x2="3.636" y2="8.636" stroke="#ffffff"></line>
<line x1="1" y1="23" x2="17" y2="23"></line>
<line x1="17" y1="9" x2="23" y2="15"></line>
</g>
</svg>
' %}
{% set notifications_bid_accepted_svg = '
<svg class="w-5 h-5" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 24 24">
<g fill="#ffffff">
<path d="M8.5,20a1.5,1.5,0,0,1-1.061-.439L.379,12.5,2.5,10.379l6,6,13-13L23.621,5.5,9.561,19.561A1.5,1.5,0,0,1,8.5,20Z" fill="#ffffff"></path>
</g>
</svg>
' %}
{% set notifications_unknow_event_svg = '
<svg class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 24 24">
<g fill="#ffffff">
<path d="M8.5,20a1.5,1.5,0,0,1-1.061-.439L.379,12.5,2.5,10.379l6,6,13-13L23.621,5.5,9.561,19.561A1.5,1.5,0,0,1,8.5,20Z" fill="#ffffff"></path>
</g>
</svg>
' %}
{% set notifications_close_svg = '
<svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
</svg>
' %}
{% set green_cross_close_svg = '
<svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
</svg>
' %}
{% set red_cross_close_svg = '
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
</svg>
' %}
{% set blue_cross_close_svg = '
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
</svg>
' %}
{% set white_automation_svg = '
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
<line data-cap="butt" x1="5" y1="1" x2="5" y2="6" stroke="#ffffff"></line>
<line x1="3" y1="1" x2="7" y2="1" stroke="#fffffwww"></line>
<line data-cap="butt" x1="19" y1="1" x2="19" y2="6" stroke="#ffffff"></line>
<line x1="17" y1="1" x2="21" y2="1" stroke="#ffffff"></line>
<rect x="6" y="15" width="12" height="4" stroke="#ffffff"></rect>
<line data-cap="butt" x1="10" y1="19" x2="10" y2="15" stroke="#ffffff"></line>
<line data-cap="butt" x1="14" y1="19" x2="14" y2="15" stroke="#ffffff"></line>
<line x1="6" y1="11" x2="8" y2="11" stroke="#ffffff"></line>
<line x1="16" y1="11" x2="18" y2="11" stroke="#fff"></line>
<polygon points="23 6 5 6 1 6 1 23 23 23 23 6"></polygon>
</g>
</svg>
' %}
{% set start_process_svg = '
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="square" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="miter" class="nc-icon-wrapper" stroke-miterlimit="10">
<polyline points="2.966 1.13 2.237 6.927 7.929 5.341"></polyline>
<path d="M2.921,18.2a11.006,11.006,0,0,1-1.041-1.9" stroke="#ffffff"></path>
<path d="M8.461,22.412a11.07,11.07,0,0,1-1.529-.654q-.2-.1-.392-.214" stroke="#ffffff"></path>
<path d="M15.539,22.41a11.062,11.062,0,0,1-2.06.486" stroke="#ffffff"></path>
<path d="M21.08,18.206a10.984,10.984,0,0,1-1.438,1.705" stroke="#ffffff"></path>
<path d="M2.759,6.027A11,11,0,0,1,22.9,13.464"></path>
</g>
</svg>
' %}
{% set love_svg = '
<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#f80b0b" stroke-linejoin="round">
<path d="M21.243,3.757 c-2.343-2.343-6.142-2.343-8.485,0c-0.289,0.289-0.54,0.6-0.757,0.927c-0.217-0.327-0.469-0.639-0.757-0.927 c-2.343-2.343-6.142-2.343-8.485,0c-2.343,2.343-2.343,6.142,0,8.485L12,21.485l9.243-9.243C23.586,9.899,23.586,6.1,21.243,3.757z"></path>
</g>
</svg>
' %}
{% set github_svg = '
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9 0C4.0275 0 0 4.13211 0 9.22838C0 13.3065 2.5785 16.7648 6.15375 17.9841C6.60375 18.0709 6.76875 17.7853 6.76875 17.5403C6.76875 17.3212 6.76125 16.7405 6.7575 15.9712C4.254 16.5277 3.726 14.7332 3.726 14.7332C3.3165 13.6681 2.72475 13.3832 2.72475 13.3832C1.9095 12.8111 2.78775 12.8229 2.78775 12.8229C3.6915 12.887 4.16625 13.7737 4.16625 13.7737C4.96875 15.1847 6.273 14.777 6.7875 14.5414C6.8685 13.9443 7.10025 13.5381 7.3575 13.3073C5.35875 13.0764 3.258 12.2829 3.258 8.74709C3.258 7.73988 3.60675 6.91659 4.18425 6.27095C4.083 6.03774 3.77925 5.0994 4.263 3.82846C4.263 3.82846 5.01675 3.58116 6.738 4.77462C7.458 4.56958 8.223 4.46785 8.988 4.46315C9.753 4.46785 10.518 4.56958 11.238 4.77462C12.948 3.58116 13.7017 3.82846 13.7017 3.82846C14.1855 5.0994 13.8818 6.03774 13.7917 6.27095C14.3655 6.91659 14.7142 7.73988 14.7142 8.74709C14.7142 12.2923 12.6105 13.0725 10.608 13.2995C10.923 13.5765 11.2155 14.1423 11.2155 15.0071C11.2155 16.242 11.2043 17.2344 11.2043 17.5341C11.2043 17.7759 11.3617 18.0647 11.823 17.9723C15.4237 16.7609 18 13.3002 18 9.22838C18 4.13211 13.9703 0 9 0Z" fill="currentColor"></path>
</svg>
' %}
{% set index_wallet_svg = '
<svg width="21" height="21" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
<path d="M6,3H3C1.895,3,1,3.895,1,5 v0c0,1.105,0.895,2,2,2"></path>
<polyline points=" 6,7 6,1 20,1 20,7 " stroke="#ffffff"></polyline>
<path d="M23,7H3 C1.895,7,1,6.105,1,5v15c0,1.657,1.343,3,3,3h19V7z"></path>
<circle cx="17" cy="15" r="2"></circle>
</g>
</svg>
' %}
{% set index_trading_svg = '
<svg width="21" height="21" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
<circle cx="5" cy="5" r="4"></circle>
<circle cx="19" cy="19" r="4"></circle>
<polyline data-cap="butt" points="13,5 21,5 21,11 " stroke="#ffffff"></polyline>
<polyline data-cap="butt" points="11,19 3,19 3,13 " stroke="#ffffff"></polyline>
<polyline points=" 16,2 13,5 16,8 " stroke="#ffffff"></polyline>
<polyline points=" 8,16 11,19 8,22 " stroke="#ffffff"></polyline>
</g>
</svg>
' %}
{% set index_support_svg = '
<svg width="22" height="22" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
<line x1="23" y1="11" x2="23" y2="16" stroke="#ffffff"></line>
<polygon points="12,13 2,8 12,3 22,8 "></polygon>
<path data-cap="butt" d="M5,9.5V18c0,1.657,3.134,3,7,3 s7-1.343,7-3V9.5"></path>
</g>
</svg>
' %}
{% set circle_plus_svg = '
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g stroke-linecap="square" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="miter" class="nc-icon-wrapper" stroke-miterlimit="10">
<line x1="12" y1="7" x2="12" y2="17" stroke="#ffffff"></line>
<line x1="17" y1="12" x2="7" y2="12" stroke="#ffffff"></line>
<circle cx="12" cy="12" r="11"></circle>
</g>
</svg>
' %}
{% set small_arrow_white_right_svg = '
<svg aria-hidden="true " class="w-5 h-5 ml-3 mr-3" fill="currentColor " viewBox="0 0 20 20 " xmlns="http://www.w3.org/2000/svg ">
<path fill-rule="evenodd " d="M12.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-2.293-2.293a1 1 0 010-1.414z " clip-rule="evenodd "></path>
</svg>
' %}
{% set circular_error_messages_svg = '
<svg class="relative top-0.5" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.4733 5.52667C10.4114 5.46419 10.3376 5.41459 10.2564 5.38075C10.1751 5.3469 10.088 5.32947 9.99999 5.32947C9.91198 5.32947 9.82485 5.3469 9.74361 5.38075C9.66237 5.41459 9.58863 5.46419 9.52666 5.52667L7.99999 7.06001L6.47333 5.52667C6.34779 5.40114 6.17753 5.33061 5.99999 5.33061C5.82246 5.33061 5.65219 5.40114 5.52666 5.52667C5.40112 5.65221 5.3306 5.82247 5.3306 6.00001C5.3306 6.17754 5.40112 6.3478 5.52666 6.47334L7.05999 8.00001L5.52666 9.52667C5.46417 9.58865 5.41458 9.66238 5.38073 9.74362C5.34689 9.82486 5.32946 9.912 5.32946 10C5.32946 10.088 5.34689 10.1752 5.38073 10.2564C5.41458 10.3376 5.46417 10.4114 5.52666 10.4733C5.58863 10.5358 5.66237 10.5854 5.74361 10.6193C5.82485 10.6531 5.91198 10.6705 5.99999 10.6705C6.088 10.6705 6.17514 10.6531 6.25638 10.6193C6.33762 10.5854 6.41135 10.5358 6.47333 10.4733L7.99999 8.94001L9.52666 10.4733C9.58863 10.5358 9.66237 10.5854 9.74361 10.6193C9.82485 10.6531 9.91198 10.6705 9.99999 10.6705C10.088 10.6705 10.1751 10.6531 10.2564 10.6193C10.3376 10.5854 10.4114 10.5358 10.4733 10.4733C10.5358 10.4114 10.5854 10.3376 10.6193 10.2564C10.6531 10.1752 10.6705 10.088 10.6705 10C10.6705 9.912 10.6531 9.82486 10.6193 9.74362C10.5854 9.66238 10.5358 9.58865 10.4733 9.52667L8.93999 8.00001L10.4733 6.47334C10.5358 6.41137 10.5854 6.33763 10.6193 6.25639C10.6531 6.17515 10.6705 6.08802 10.6705 6.00001C10.6705 5.912 10.6531 5.82486 10.6193 5.74362C10.5854 5.66238 10.5358 5.58865 10.4733 5.52667ZM12.7133 3.28667C12.0983 2.64994 11.3627 2.14206 10.5494 1.79266C9.736 1.44327 8.8612 1.25936 7.976 1.25167C7.0908 1.24398 6.21294 1.41266 5.39363 1.74786C4.57432 2.08307 3.82998 2.57809 3.20403 3.20404C2.57807 3.82999 2.08305 4.57434 1.74785 5.39365C1.41264 6.21296 1.24396 7.09082 1.25166 7.97602C1.25935 8.86121 1.44326 9.73601 1.79265 10.5494C2.14204 11.3627 2.64992 12.0984 3.28666 12.7133C3.90164 13.3501 4.63727 13.858 5.45063 14.2074C6.26399 14.5567 7.13879 14.7407 8.02398 14.7483C8.90918 14.756 9.78704 14.5874 10.6064 14.2522C11.4257 13.9169 12.17 13.4219 12.796 12.796C13.4219 12.17 13.9169 11.4257 14.2521 10.6064C14.5873 9.78706 14.756 8.90919 14.7483 8.024C14.7406 7.1388 14.5567 6.264 14.2073 5.45064C13.8579 4.63728 13.3501 3.90165 12.7133 3.28667ZM11.7733 11.7733C10.9014 12.6463 9.75368 13.1899 8.52585 13.3115C7.29802 13.4332 6.066 13.1254 5.03967 12.4405C4.01335 11.7557 3.25623 10.7361 2.89731 9.55566C2.53838 8.37518 2.59986 7.10677 3.07127 5.96653C3.54267 4.82629 4.39484 3.88477 5.48259 3.30238C6.57033 2.71999 7.82635 2.53276 9.03666 2.77259C10.247 3.01242 11.3367 3.66447 12.1202 4.61765C12.9036 5.57083 13.3324 6.76617 13.3333 8.00001C13.3357 8.70087 13.1991 9.39524 12.9313 10.0429C12.6635 10.6906 12.2699 11.2788 11.7733 11.7733Z" fill="#EF5944"></path>
</svg>
' %}
{% set confirm_green_svg = '
<svg class="relative top-0.5" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12.4732 4.80667C12.4112 4.74418 12.3375 4.69458 12.2563 4.66074C12.175 4.62689 12.0879 4.60947 11.9999 4.60947C11.9119 4.60947 11.8247 4.62689 11.7435 4.66074C11.6623 4.69458 11.5885 4.74418 11.5266 4.80667L6.55989 9.78L4.47322 7.68667C4.40887 7.62451 4.33291 7.57563 4.24967 7.54283C4.16644 7.51003 4.07755 7.49394 3.9881 7.49549C3.89865 7.49703 3.81037 7.51619 3.72832 7.55185C3.64627 7.58751 3.57204 7.63898 3.50989 7.70333C3.44773 7.76768 3.39885 7.84364 3.36605 7.92688C3.33324 8.01011 3.31716 8.099 3.31871 8.18845C3.32025 8.2779 3.3394 8.36618 3.37507 8.44823C3.41073 8.53028 3.4622 8.60451 3.52655 8.66667L6.08655 11.2267C6.14853 11.2892 6.22226 11.3387 6.3035 11.3726C6.38474 11.4064 6.47188 11.4239 6.55989 11.4239C6.64789 11.4239 6.73503 11.4064 6.81627 11.3726C6.89751 11.3387 6.97124 11.2892 7.03322 11.2267L12.4732 5.78667C12.5409 5.72424 12.5949 5.64847 12.6318 5.56414C12.6688 5.4798 12.6878 5.38873 12.6878 5.29667C12.6878 5.2046 12.6688 5.11353 12.6318 5.02919C12.5949 4.94486 12.5409 4.86909 12.4732 4.80667Z" fill="#2AD168"></path>
</svg>
<svg aria-hidden="true" width="16" height="16" class="relative top-0.5" fill="#2AD168" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"></path>
</svg>
' %}
{% set circular_info_messages_svg = '
<svg aria-hidden="true" width="16" height="16" class="relative top-0.5" fill="#2AD168" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"></path>
</svg>
' %}
{% set circular_update_messages_svg = '
<svg aria-hidden="true" width="16" height="16" class="relative top-0.5" fill="#3b82f6" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"></path>
</svg>
' %}
{% set input_down_arrow_offer_svg = '
<svg class="absolute right-4 top-1/2 transform -translate-y-1/2 z-50" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
</svg>
' %}
{% set select_network_svg = '
<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<line data-cap="butt" x1="7.6" y1="10.5" x2="16.4" y2="5.5" stroke="#3b82f6"></line>
<line data-cap="butt" x1="7.6" y1="13.5" x2="16.4" y2="18.5" stroke="#3b82f6"></line>
<circle cx="5" cy="12" r="3"></circle>
<circle cx="19" cy="4" r="3"></circle>
<circle cx="19" cy="20" r="3"></circle>
</g>
</svg>
' %}
{% set select_address_svg = '
<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="square" stroke-miterlimit="10" fill="#3b82f6" stroke-linejoin="miter">
<circle cx="8" cy="6" r="4" fill="none" stroke="#3b82f6" stroke-width="2"></circle>
<line x1="23" y1="5" x2="16" y2="5" fill="none" stroke="#3b82f6" stroke-width="2" data-color="color-2"></line>
<line x1="23" y1="10" x2="16" y2="10" fill="none" stroke="#3b82f6" stroke-width="2" data-color="color-2"></line>
<line x1="23" y1="15" x2="18" y2="15" fill="none" stroke="#3b82f6" stroke-width="2" data-color="color-2"></line>
<path d="M8,14c-3.866,0-7,3.134-7,7v1H15v-1c0-3.866-3.134-7-7-7Z" fill="none" stroke="#3b82f6" stroke-width="2"></path>
</g>
</svg>
' %}
{% set select_swap_type_svg = '
<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24"><g stroke-linecap="square" stroke-miterlimit="10" fill="#3b82f6" stroke-linejoin="miter">
<line data-cap="butt" data-color="color-2" fill="none" stroke="#3b82f6" stroke-width="2" x1="7" y1="17" x2="22" y2="17" stroke-linecap="butt"></line>
<polyline data-color="color-2" fill="none" stroke="#3b82f6" stroke-width="2" points=" 18,21 22,17 18,13 "></polyline>
<line data-cap="butt" fill="none" stroke="#3b82f6" stroke-width="2" x1="18" y1="7" x2="2" y2="7" stroke-linecap="butt"></line>
<polyline fill="none" stroke="#3b82f6" stroke-width="2" points="6,11 2,7 6,3 ">
</polyline>
</g>
</svg>
' %}
{% set select_bid_amount_svg = '
<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<rect x="9.843" y="5.379" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -0.7635 13.1569)" width="11.314" height="4.243"></rect>
<polyline points="3,23 3,19 15,19 15,23 "></polyline>
<line x1="4" y1="15" x2="1" y2="15" stroke="#3b82f6"></line>
<line x1="5.757" y1="10.757" x2="3.636" y2="8.636" stroke="#3b82f6"></line>
<line x1="1" y1="23" x2="17" y2="23"></line>
<line x1="17" y1="9" x2="23" y2="15"></line>
</g>
</svg>
' %}
{% set select_rate_svg = '
<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="square" stroke-miterlimit="10" fill="#3b82f6" stroke-linejoin="miter">
<circle fill="none" stroke="#3b82f6" stroke-width="2" cx="12" cy="12" r="11"></circle>
<circle data-color="color-2" fill="none" stroke="#3b82f6" stroke-width="2" cx="8" cy="8" r="2"></circle>
<circle data-color="color-2" fill="none" stroke="#3b82f6" stroke-width="2" cx="16" cy="16" r="2"></circle>
<line data-color="color-2" fill="none" stroke="#3b82f6" stroke-width="2" x1="8" y1="16" x2="16" y2="8"></line></g>
</svg>
' %}
{% set step_one_svg = '
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 24 24">
<g fill="#3b82f6">
<polygon points="14.5 23.5 11.5 23.5 11.5 4.321 6.766 8.108 4.892 5.766 11.474 0.5 14.5 0.5 14.5 23.5" fill="#3b82f6"></polygon>
</g>
</svg>
' %}
{% set step_two_svg = '
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 24 24">
<g fill="#3b82f6">
<path d="M19.5,23.5H4.5V20.2l.667-.445C9.549,16.828,16.5,10.78,16.5,7c0-2.654-1.682-4-5-4A9.108,9.108,0,0,0,7.333,4.248L6.084,5.08,4.42,2.584l1.247-.832A11.963,11.963,0,0,1,11.5,0c4.935,0,8,2.683,8,7,0,5-6.5,10.662-10.232,13.5H19.5ZM6,21H6Z" fill="#3b82f6"></path>
</g>
</svg>
' %}
{% set step_three_svg = '
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 24 24">
<g fill="#3b82f6">
<polygon points="9 21 1 13 4 10 9 15 21 3 24 6 9 21" fill="#3b82f6"></polygon>
</g>
</svg>
' %}
{% set select_setup_svg = '
<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<path d="M15.6,13.873a2.273,2.273,0,0,1-.825,1.833,4.1,4.1,0,0,1-2.31.829v1.47h-.982V16.563a7.95,7.95,0,0,1-3.07-.617V14.053a8.328,8.328,0,0,0,1.5.545,8.019,8.019,0,0,0,1.568.28V12.654L11,12.468a5.357,5.357,0,0,1-2.012-1.216A2.332,2.332,0,0,1,8.4,9.627a2.123,2.123,0,0,1,.814-1.71,4.143,4.143,0,0,1,2.27-.812v-1.1h.982V7.074a8.126,8.126,0,0,1,2.97.66l-.674,1.678a7.768,7.768,0,0,0-2.3-.559v2.116a11.073,11.073,0,0,1,1.991.932,2.733,2.733,0,0,1,.867.868A2.146,2.146,0,0,1,15.6,13.873ZM10.558,9.627a.678.678,0,0,0,.219.52,2.569,2.569,0,0,0,.707.42V8.881Q10.559,9.017,10.558,9.627Zm2.884,4.354a.646.646,0,0,0-.244-.509,3.173,3.173,0,0,0-.732-.431v1.786Q13.441,14.662,13.442,13.981Z" stroke="none" fill="#3b82f6"></path>
<polyline points="5.346 7.929 6.932 2.237 1.135 2.966"></polyline>
<path data-cap="butt" d="M11.789,23A11,11,0,0,1,6.932,2.237"></path>
<polyline points="18.654 16.071 17.068 21.763 22.865 21.034"></polyline>
<path data-cap="butt" d="M12.211,1a11,11,0,0,1,4.857,20.763"></path>
</g>
</svg>
' %}
{% set select_auto_strategy_svg = '
<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round">
<circle cx="12" cy="12" r="5" stroke="#3b82f6" data-cap="butt"></circle>
<polygon points="5 6 2 4 5 2 5 6" fill="#3b82f6" stroke="none"></polygon>
<polygon points="19 18 22 20 19 22 19 18" fill="#3b82f6" stroke="none"></polygon>
<polygon points="5 6 2 4 5 2 5 6"></polygon>
<line x1="5" y1="4" x2="9" y2="4"></line>
<polygon points="19 18 22 20 19 22 19 18"></polygon>
<line x1="19" y1="20" x2="15" y2="20"></line>
</g>
</svg>
' %}
{% set input_time_svg = '
<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="square" stroke-miterlimit="10" fill="#3b82f6" stroke-linejoin="miter">
<circle fill="none" stroke="#3b82f6" stroke-width="2" cx="12" cy="12" r="11"></circle>
<polyline data-color="color-2" fill="none" stroke="#3b82f6" stroke-width="2" points=" 12,6 12,12 18,12 "></polyline></g>
</svg>
' %}
{% set select_target_svg = '
<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
<g stroke-linecap="square" stroke-miterlimit="10" fill="#3b82f6" stroke-linejoin="miter">
<circle fill="none" stroke="#3b82f6" stroke-width="2" cx="12" cy="12" r="11"></circle>
<circle data-color="color-2" fill="none" stroke="#3b82f6" stroke-width="2" cx="12" cy="12" r="7"></circle>
<circle fill="none" stroke="#3b82f6" stroke-width="2" cx="12" cy="12" r="3"></circle>
</g>
</svg>
' %} ' %}
{% set select_box_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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0' %} {% set select_box_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-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0' %}

View File

@@ -1,5 +1,4 @@
{% include 'header.html' %} {% include 'header.html' %}
{% from 'style.html' import breadcrumb_line_svg, circular_arrows_svg %}
<div class="container mx-auto"> <div class="container mx-auto">
<section class="p-5 mt-5"> <section class="p-5 mt-5">
<div class="flex flex-wrap items-center -m-2"> <div class="flex flex-wrap items-center -m-2">
@@ -10,11 +9,19 @@
<p>Home</p> <p>Home</p>
</a> </a>
</li> </li>
<li>{{ breadcrumb_line_svg | safe }}</li> <li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
<li> <li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/tor">Tor</a> <a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/tor">Tor</a>
</li> </li>
<li>{{ breadcrumb_line_svg | safe }}</li> <li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
</ul> </ul>
</div> </div>
</div> </div>
@@ -32,13 +39,23 @@
</div> </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"> <div class="w-full md:w-1/2 p-3 p-6 container flex flex-wrap items-center justify-end items-center mx-auto">
{% if refresh %} {% if refresh %}
<a id="refresh" href="/tor" class="rounded-full 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"> <a id="refresh" href="/tor" class="flex flex-wrap justify-center px-5 py-4 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white border dark:text-white dark:hover:text-white dark:bg-gray-600 dark:hover:bg-gray-700 dark:border-gray-600 dark:hover:border-gray-600 rounded-md shadow-button focus:ring-0 focus:outline-none">
{{ circular_arrows_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g fill="#ffffff">
<path fill="#ffffff" d="M12,3c1.989,0,3.873,0.65,5.43,1.833l-3.604,3.393l9.167,0.983L22.562,0l-3.655,3.442 C16.957,1.862,14.545,1,12,1C5.935,1,1,5.935,1,12h2C3,7.037,7.037,3,12,3z"></path>
<path data-color="color-2" d="M12,21c-1.989,0-3.873-0.65-5.43-1.833l3.604-3.393l-9.167-0.983L1.438,24l3.655-3.442 C7.043,22.138,9.455,23,12,23c6.065,0,11-4.935,11-11h-2C21,16.963,16.963,21,12,21z"></path>
</g>
</svg>
<span>Refresh {{ refresh }} seconds</span> <span>Refresh {{ refresh }} seconds</span>
</a> </a>
{% else %} {% else %}
<a id="refresh" href="/tor" class="rounded-full 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"> <a id="refresh" href="/tor" class="flex flex-wrap justify-center px-5 py-4 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white borderdark:text-white dark:hover:text-white dark:bg-gray-600 dark:hover:bg-gray-700 dark:border-gray-600 dark:hover:border-gray-600 border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none">
{{ circular_arrows_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g fill="#ffffff">
<path fill="#ffffff" d="M12,3c1.989,0,3.873,0.65,5.43,1.833l-3.604,3.393l9.167,0.983L22.562,0l-3.655,3.442 C16.957,1.862,14.545,1,12,1C5.935,1,1,5.935,1,12h2C3,7.037,7.037,3,12,3z"></path>
<path data-color="color-2" d="M12,21c-1.989,0-3.873-0.65-5.43-1.833l3.604-3.393l-9.167-0.983L1.438,24l3.655-3.442 C7.043,22.138,9.455,23,12,23c6.065,0,11-4.935,11-11h-2C21,16.963,16.963,21,12,21z"></path>
</g>
</svg>
<span>Refresh</span> <span>Refresh</span>
</a> </a>
{% endif %} {% endif %}

View File

@@ -103,7 +103,7 @@
<a class="inline-block text-xs font-medium text-blue-500 hover:text-blue-600 hover:underline" href="https://academy.particl.io/en/latest/faq/get_support.html" target="_blank" contenteditable="false">Help / Tutorials</a> <a class="inline-block text-xs font-medium text-blue-500 hover:text-blue-600 hover:underline" href="https://academy.particl.io/en/latest/faq/get_support.html" target="_blank" contenteditable="false">Help / Tutorials</a>
</p> </p>
<p class="text-center"> <p class="text-center">
<span class="text-xs font-medium text-coolGray-500 dark:text-gray-500" contenteditable="false">{{ title }} - GUI 3.0.0</span> <span class="text-xs font-medium text-coolGray-500 dark:text-gray-500" contenteditable="false">{{ title }} - GUI 2.0.2</span>
</p> </p>
<input type="hidden" name="formid" value="{{ form_id }}"> <input type="hidden" name="formid" value="{{ form_id }}">
</form> </form>

File diff suppressed because it is too large Load Diff

View File

@@ -53,7 +53,7 @@
{% if w.error %}<p>Error: {{ w.error }}</p> {% if w.error %}<p>Error: {{ w.error }}</p>
{% else %} {% else %}
<div class="w-full lg:w-1/3 p-4"> <div class="w-full lg:w-1/3 p-4">
<div class="bg-gray-50 rounded overflow-hidden dark:bg-gray-500"> <div class="bg-gray-50 shadow rounded overflow-hidden dark:bg-gray-500">
<div class="pt-6 px-6 mb-10 flex justify-between items-center"> <div class="pt-6 px-6 mb-10 flex justify-between items-center">
<span class="inline-flex items-center justify-center w-9 h-10 bg-white-50 rounded"> <span class="inline-flex items-center justify-center w-9 h-10 bg-white-50 rounded">
<img class="h-9" src="/static/images/coins/{{ w.name }}.png" alt="{{ w.name }}"> <img class="h-9" src="/static/images/coins/{{ w.name }}.png" alt="{{ w.name }}">
@@ -73,8 +73,8 @@
<div class="bold inline-block py-1 px-2 rounded-full bg-blue-100 text-xs text-black-500 dark:bg-gray-500 dark:text-gray-200 coinname-value" data-coinname="{{ w.name }}">{{ w.balance }} {{ w.ticker }}</div> <div class="bold inline-block py-1 px-2 rounded-full bg-blue-100 text-xs text-black-500 dark:bg-gray-500 dark:text-gray-200 coinname-value" data-coinname="{{ w.name }}">{{ w.balance }} {{ w.ticker }}</div>
</div> </div>
<div class="flex mb-2 justify-between items-center"> <div class="flex mb-2 justify-between items-center">
<h4 class="text-xs font-medium dark:text-white usd-text">{{ w.ticker }} USD value:</h4> <h4 class="text-xs font-medium dark:text-white">{{ w.ticker }} USD value:</h4>
<div class="bold inline-block py-1 px-2 rounded-full bg-blue-100 text-xs text-black-500 dark:bg-gray-500 dark:text-gray-200 usd-value" data-coinname="{{ w.name }}"></div> <div class="bold inline-block py-1 px-2 rounded-full bg-blue-100 text-xs text-black-500 dark:bg-gray-500 dark:text-gray-200 usd-value"></div>
</div> </div>
{% if w.pending %} {% if w.pending %}
<div class="flex mb-2 justify-between items-center"> <div class="flex mb-2 justify-between items-center">
@@ -178,21 +178,8 @@
<span class="text-xs font-medium dark:text-gray-200">Blockchain</span> <span class="text-xs font-medium dark:text-gray-200">Blockchain</span>
<span class="text-xs font-medium dark:text-gray-200">{{ w.synced }}%</span> <span class="text-xs font-medium dark:text-gray-200">{{ w.synced }}%</span>
</div> </div>
<div class="w-full bg-gray-200 rounded-full h-1 " data-tooltip-target="tooltip-blocks{{loop.index}}"> <div class="w-full bg-gray-200 rounded-full h-1">
<div class="{% if w.synced | float < 100 %} bg-red-500 sync-bar-color-change {% else %} bg-blue-500 {% endif %} h-1 rounded-full" style="width: {{ w.synced }}%;"></div> <div class="bg-blue-500 h-1 rounded-full" style="width: {{ w.synced }}%"></div>
</div>
<div class="flex justify-between mb-1 mt-5">
<span class="text-xs font-medium dark:text-gray-200">
<script>
if ({{ w.synced }} !== 100) {
document.write("<p class='bg-gray-50 rounded overflow-hidden dark:bg-gray-500 p-2.5 dark:text-white'>The order book/blockchain is currently syncing, offers will only display once the network has fully <b>100%</b> synced. Please wait until the process completes.</p>");
}
</script>
<div id="tooltip-blocks{{loop.index}}" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-xs text-white {% if w.synced | float < 100 %} bg-red-500 sync-bar-color-change {% else %} bg-blue-500 {% endif %} rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
<div><span class="bold">Blocks: {{ w.blocks }}{% if w.known_block_count %} / {{ w.known_block_count }} {% endif %}</div>
<div class="tooltip-arrow pl-1" data-popper-arrow></div>
</div>
</span>
</div> </div>
</div> </div>
</div> </div>
@@ -216,10 +203,7 @@ const coinNameToSymbol = {
'Litecoin': 'LTC', 'Litecoin': 'LTC',
'Firo': 'FIRO', 'Firo': 'FIRO',
'Dash': 'DASH', 'Dash': 'DASH',
'PIVX': 'PIVX', 'PIVX': 'PIVX'
'Wownero': 'WOW',
'Decred': 'DCR',
'Zano': 'ZANO',
}; };
const getUsdValue = (cryptoValue, coinSymbol) => { const getUsdValue = (cryptoValue, coinSymbol) => {
@@ -271,40 +255,21 @@ const updateValues = async () => {
calculateTotalBtcValue(); calculateTotalBtcValue();
}; };
const toggleUsdAmount = async (usdCell, isVisible) => { const toggleUsdAmount = (usdCell, isVisible) => {
const usdText = document.getElementById('usd-text'); const usdText = document.getElementById('usd-text');
if (usdText) { if (usdText) {
usdText.style.display = isVisible ? 'inline' : 'none'; usdText.style.display = isVisible ? 'inline' : 'none';
} }
if (isVisible) { if (isVisible) {
const coinNameValueElement = usdCell.parentElement.querySelector('.coinname-value'); const coinFullName = usdCell.previousElementSibling.getAttribute('data-coinname');
const cryptoValue = parseFloat(usdCell.previousElementSibling.textContent);
const coinSymbol = coinNameToSymbol[coinFullName];
if (coinNameValueElement) {
const coinFullName = coinNameValueElement.getAttribute('data-coinname');
console.log("coinFullName:", coinFullName);
if (coinFullName) {
const cryptoValue = parseFloat(coinNameValueElement.textContent);
console.log("cryptoValue:", cryptoValue);
const coinSymbol = coinNameToSymbol[coinFullName.trim()];
console.log("coinSymbol:", coinSymbol);
if (coinSymbol) { if (coinSymbol) {
await updateValues(); updateValues();
} else { } else {
console.error(`Coin symbol not found for full name: ${coinFullName}`); console.error(`Coin symbol not found for full name: ${coinFullName}`);
} }
} else {
console.error(`Data attribute 'data-coinname' not found.`);
}
} else {
}
} else { } else {
usdCell.textContent = "******"; usdCell.textContent = "******";
const btcValueElement = usdCell.nextElementSibling; const btcValueElement = usdCell.nextElementSibling;

View File

@@ -1,5 +1,4 @@
{% include 'header.html' %} {% include 'header.html' %}
{% from 'style.html' import breadcrumb_line_svg, circular_arrows_svg %}
<div class="container mx-auto"> <div class="container mx-auto">
<section class="p-5 mt-5"> <section class="p-5 mt-5">
<div class="flex flex-wrap items-center -m-2"> <div class="flex flex-wrap items-center -m-2">
@@ -10,11 +9,19 @@
<p>Home</p> <p>Home</p>
</a> </a>
</li> </li>
<li>{{ breadcrumb_line_svg | safe }}</li> <li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
<li> <li>
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/watched">Watched Outputs</a> <a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/watched">Watched Outputs</a>
</li> </li>
<li>{{ breadcrumb_line_svg | safe }}</li> <li>
<svg width="6" height="15" viewBox="0 0 6 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.34 0.671999L2.076 14.1H0.732L3.984 0.671999H5.34Z" fill="#BBC3CF"></path>
</svg>
</li>
</ul> </ul>
</div> </div>
</div> </div>
@@ -32,13 +39,23 @@
</div> </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"> <div class="w-full md:w-1/2 p-3 p-6 container flex flex-wrap items-center justify-end items-center mx-auto">
{% if refresh %} {% if refresh %}
<a id="refresh" href="/watched" class="rounded-full 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"> <a id="refresh" href="/watched" class="flex flex-wrap justify-center px-5 py-4 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white border dark:text-white dark:hover:text-white dark:bg-gray-600 dark:hover:bg-gray-700 dark:border-gray-600 dark:hover:border-gray-600 rounded-md shadow-button focus:ring-0 focus:outline-none">
{{ circular_arrows_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g fill="#ffffff">
<path fill="#ffffff" d="M12,3c1.989,0,3.873,0.65,5.43,1.833l-3.604,3.393l9.167,0.983L22.562,0l-3.655,3.442 C16.957,1.862,14.545,1,12,1C5.935,1,1,5.935,1,12h2C3,7.037,7.037,3,12,3z"></path>
<path data-color="color-2" d="M12,21c-1.989,0-3.873-0.65-5.43-1.833l3.604-3.393l-9.167-0.983L1.438,24l3.655-3.442 C7.043,22.138,9.455,23,12,23c6.065,0,11-4.935,11-11h-2C21,16.963,16.963,21,12,21z"></path>
</g>
</svg>
<span>Refresh {{ refresh }} seconds</span> <span>Refresh {{ refresh }} seconds</span>
</a> </a>
{% else %} {% else %}
<a id="refresh" href="/watched" class="rounded-full 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"> <a id="refresh" href="/watched" class="flex flex-wrap justify-center px-5 py-4 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white borderdark:text-white dark:hover:text-white dark:bg-gray-600 dark:hover:bg-gray-700 dark:border-gray-600 dark:hover:border-gray-600 border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none">
{{ circular_arrows_svg | safe }} <svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
<g fill="#ffffff">
<path fill="#ffffff" d="M12,3c1.989,0,3.873,0.65,5.43,1.833l-3.604,3.393l9.167,0.983L22.562,0l-3.655,3.442 C16.957,1.862,14.545,1,12,1C5.935,1,1,5.935,1,12h2C3,7.037,7.037,3,12,3z"></path>
<path data-color="color-2" d="M12,21c-1.989,0-3.873-0.65-5.43-1.833l3.604-3.393l-9.167-0.983L1.438,24l3.655-3.442 C7.043,22.138,9.455,23,12,23c6.065,0,11-4.935,11-11h-2C21,16.963,16.963,21,12,21z"></path>
</g>
</svg>
<span>Refresh</span> <span>Refresh</span>
</a> </a>
{% endif %} {% endif %}

View File

@@ -108,7 +108,11 @@ def page_bid(self, url_split, post_string):
if len(data['addr_from_label']) > 0: if len(data['addr_from_label']) > 0:
data['addr_from_label'] = '(' + data['addr_from_label'] + ')' data['addr_from_label'] = '(' + data['addr_from_label'] + ')'
data['can_accept_bid'] = True if bid.state == BidStates.BID_RECEIVED else False
page_data = {
'bid_states': listBidStates(),
'bid_actions': []
}
if swap_client.debug_ui: if swap_client.debug_ui:
data['bid_actions'] = [(-1, 'None'), ] + listBidActions() data['bid_actions'] = [(-1, 'None'), ] + listBidActions()
@@ -197,5 +201,4 @@ def page_bids(self, url_split, post_string, sent=False, available=False, receive
'summary': summary, 'summary': summary,
'bids': [(format_timestamp(b[0]), 'bids': [(format_timestamp(b[0]),
b[2].hex(), b[3].hex(), strBidState(b[5]), strTxState(b[7]), strTxState(b[8]), b[11]) for b in bids], b[2].hex(), b[3].hex(), strBidState(b[5]), strTxState(b[7]), strTxState(b[8]), b[11]) for b in bids],
'bids_count': len(bids),
}) })

View File

@@ -5,19 +5,17 @@
# file LICENSE or http://www.opensource.org/licenses/mit-license.php. # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
import traceback import traceback
import time
from urllib import parse from urllib import parse
from .util import ( from .util import (
getCoinType,
get_data_entry,
get_data_entry_or,
have_data_entry,
inputAmount,
known_chart_coins,
listAvailableCoins,
PAGE_LIMIT, PAGE_LIMIT,
getCoinType,
inputAmount,
setCoinFilter, setCoinFilter,
get_data_entry,
have_data_entry,
get_data_entry_or,
listAvailableCoins,
set_pagination_filters, set_pagination_filters,
) )
from basicswap.db import ( from basicswap.db import (
@@ -26,6 +24,7 @@ from basicswap.db import (
from basicswap.util import ( from basicswap.util import (
ensure, ensure,
format_amount, format_amount,
format_timestamp,
) )
from basicswap.basicswap_util import ( from basicswap.basicswap_util import (
SwapTypes, SwapTypes,
@@ -41,8 +40,8 @@ from basicswap.chainparams import (
Coins, Coins,
) )
default_chart_api_key = '95dd900af910656e0e17c41f2ddc5dba77d01bf8b0e7d2787634a16bd976c553' default_chart_api_key = '95dd900af910656e0e17c41f2ddc5dba77d01bf8b0e7d2787634a16bd976c553'
default_coingecko_api_key = 'CG-8hm3r9iLfpEXv4ied8oLbeUj'
def value_or_none(v): def value_or_none(v):
@@ -143,9 +142,6 @@ def parseOfferFormData(swap_client, form_data, page_data, options={}):
parsed_data['rate'] = ci_from.make_int(parsed_data['amt_to'] / parsed_data['amt_from'], r=1) parsed_data['rate'] = ci_from.make_int(parsed_data['amt_to'] / parsed_data['amt_from'], r=1)
page_data['rate'] = ci_to.format_amount(parsed_data['rate']) page_data['rate'] = ci_to.format_amount(parsed_data['rate'])
if 'amt_to' not in parsed_data and 'rate' in parsed_data and 'amt_from' in parsed_data:
parsed_data['amt_to'] = int((parsed_data['amt_from'] * parsed_data['rate']) // ci_from.COIN())
page_data['amt_var'] = True if have_data_entry(form_data, 'amt_var') else False page_data['amt_var'] = True if have_data_entry(form_data, 'amt_var') else False
parsed_data['amt_var'] = page_data['amt_var'] parsed_data['amt_var'] = page_data['amt_var']
page_data['rate_var'] = True if have_data_entry(form_data, 'rate_var') else False page_data['rate_var'] = True if have_data_entry(form_data, 'rate_var') else False
@@ -254,9 +250,7 @@ def parseOfferFormData(swap_client, form_data, page_data, options={}):
page_data['to_fee_override'] = ci_to.format_amount(ci_to.make_int(to_fee_override, r=1)) page_data['to_fee_override'] = ci_to.format_amount(ci_to.make_int(to_fee_override, r=1))
parsed_data['to_fee_override'] = page_data['to_fee_override'] parsed_data['to_fee_override'] = page_data['to_fee_override']
except Exception as e: except Exception as e:
# Error is expected if missing fields print('Error setting fee', str(e)) # Expected if missing fields
if swap_client.debug is True:
swap_client.log.warning(f'parseOfferFormData failed to set fee: Error {e}')
return parsed_data, errors return parsed_data, errors
@@ -312,8 +306,6 @@ def postNewOfferFromParsed(swap_client, parsed_data):
extra_options['automation_id'] = parsed_data['automation_strat_id'] extra_options['automation_id'] = parsed_data['automation_strat_id']
swap_value = parsed_data['amt_from'] swap_value = parsed_data['amt_from']
if parsed_data.get('amt_to', None) is not None:
extra_options['amount_to'] = parsed_data['amt_to']
if parsed_data.get('subfee', False): if parsed_data.get('subfee', False):
ci_from = swap_client.ci(parsed_data['coin_from']) ci_from = swap_client.ci(parsed_data['coin_from'])
pi = swap_client.pi(swap_type) pi = swap_client.pi(swap_type)
@@ -352,10 +344,6 @@ def offer_to_post_string(self, swap_client, offer_id):
ci_from = swap_client.ci(offer.coin_from) ci_from = swap_client.ci(offer.coin_from)
ci_to = swap_client.ci(offer.coin_to) ci_to = swap_client.ci(offer.coin_to)
amount_to: int = offer.amount_to
if amount_to is None:
amount_to = (offer.amount_from * offer.rate) // ci_from.COIN()
offer_data = { offer_data = {
'formid': self.generate_form_id(), 'formid': self.generate_form_id(),
'addr_to': offer.addr_to, 'addr_to': offer.addr_to,
@@ -368,7 +356,7 @@ def offer_to_post_string(self, swap_client, offer_id):
'amt_from': ci_from.format_amount(offer.amount_from), 'amt_from': ci_from.format_amount(offer.amount_from),
'amt_bid_min': ci_from.format_amount(offer.min_bid_amount), 'amt_bid_min': ci_from.format_amount(offer.min_bid_amount),
'rate': ci_to.format_amount(offer.rate), 'rate': ci_to.format_amount(offer.rate),
'amt_to': ci_to.format_amount(amount_to), 'amt_to': ci_to.format_amount((offer.amount_from * offer.rate) // ci_from.COIN()),
'validhrs': offer.time_valid // (60 * 60), 'validhrs': offer.time_valid // (60 * 60),
'swap_type': strSwapType(offer.swap_type), 'swap_type': strSwapType(offer.swap_type),
} }
@@ -462,11 +450,6 @@ def page_newoffer(self, url_split, post_string):
chart_api_key_enc = swap_client.settings.get('chart_api_key_enc', '') chart_api_key_enc = swap_client.settings.get('chart_api_key_enc', '')
chart_api_key = default_chart_api_key if chart_api_key_enc == '' else bytes.fromhex(chart_api_key_enc).decode('utf-8') chart_api_key = default_chart_api_key if chart_api_key_enc == '' else bytes.fromhex(chart_api_key_enc).decode('utf-8')
coingecko_api_key = swap_client.settings.get('coingecko_api_key', '')
if coingecko_api_key == '':
coingecko_api_key_enc = swap_client.settings.get('coingecko_api_key_enc', '')
coingecko_api_key = default_coingecko_api_key if coingecko_api_key_enc == '' else bytes.fromhex(coingecko_api_key_enc).decode('utf-8')
return self.render_template(template, { return self.render_template(template, {
'messages': messages, 'messages': messages,
'err_messages': err_messages, 'err_messages': err_messages,
@@ -480,7 +463,6 @@ def page_newoffer(self, url_split, post_string):
'swap_types': [(strSwapType(x), strSwapDesc(x)) for x in SwapTypes if strSwapType(x)], 'swap_types': [(strSwapType(x), strSwapDesc(x)) for x in SwapTypes if strSwapType(x)],
'show_chart': swap_client.settings.get('show_chart', True), 'show_chart': swap_client.settings.get('show_chart', True),
'chart_api_key': chart_api_key, 'chart_api_key': chart_api_key,
'coingecko_api_key': coingecko_api_key,
}) })
@@ -579,9 +561,6 @@ def page_offer(self, url_split, post_string):
err_messages.append('Send bid failed: ' + str(ex)) err_messages.append('Send bid failed: ' + str(ex))
show_bid_form = True show_bid_form = True
amount_to: int = offer.amount_to
if amount_to is None:
amount_to = (offer.amount_from * offer.rate) // ci_from.COIN()
now: int = swap_client.getTime() now: int = swap_client.getTime()
data = { data = {
'tla_from': ci_from.ticker(), 'tla_from': ci_from.ticker(),
@@ -592,7 +571,7 @@ def page_offer(self, url_split, post_string):
'coin_from_ind': int(ci_from.coin_type()), 'coin_from_ind': int(ci_from.coin_type()),
'coin_to_ind': int(ci_to.coin_type()), 'coin_to_ind': int(ci_to.coin_type()),
'amt_from': ci_from.format_amount(offer.amount_from), 'amt_from': ci_from.format_amount(offer.amount_from),
'amt_to': ci_to.format_amount(amount_to), 'amt_to': ci_to.format_amount((offer.amount_from * offer.rate) // ci_from.COIN()),
'amt_bid_min': ci_from.format_amount(offer.min_bid_amount), 'amt_bid_min': ci_from.format_amount(offer.min_bid_amount),
'rate': ci_to.format_amount(offer.rate), 'rate': ci_to.format_amount(offer.rate),
'lock_type': getLockName(offer.lock_type), 'lock_type': getLockName(offer.lock_type),
@@ -682,39 +661,6 @@ def page_offer(self, url_split, post_string):
}) })
def format_timestamp(timestamp, with_ago=True, is_expired=False):
current_time = int(time.time())
if is_expired:
time_diff = timestamp - current_time
if time_diff <= 0:
return "Expired"
else:
time_diff = current_time - timestamp
if time_diff <= 172800:
hours_ago = time_diff // 3600
minutes_ago = (time_diff % 3600) // 60
if hours_ago == 0:
if minutes_ago == 1:
return "1 min ago" if with_ago else "1 min"
else:
return f"{minutes_ago} mins ago" if with_ago else f"{minutes_ago} mins"
elif hours_ago == 1:
if minutes_ago == 0:
return "1h ago" if with_ago else "1h"
else:
return f"1h {minutes_ago}min ago" if with_ago else f"1h {minutes_ago}min"
else:
if minutes_ago == 0:
return f"{int(hours_ago)}h ago" if with_ago else f"{int(hours_ago)}h"
else:
return f"{int(hours_ago)}h {minutes_ago}min ago" if with_ago else f"{int(hours_ago)}h {minutes_ago}min"
else:
return time.strftime('%Y-%m-%d', time.localtime(timestamp))
def page_offers(self, url_split, post_string, sent=False): def page_offers(self, url_split, post_string, sent=False):
server = self.server server = self.server
swap_client = server.swap_client swap_client = server.swap_client
@@ -775,29 +721,19 @@ def page_offers(self, url_split, post_string, sent=False):
now: int = swap_client.getTime() now: int = swap_client.getTime()
formatted_offers = [] formatted_offers = []
tla_from = ""
tla_to = ""
for row in offers: for row in offers:
o, completed_amount = row o, completed_amount = row
ci_from = swap_client.ci(Coins(o.coin_from)) ci_from = swap_client.ci(Coins(o.coin_from))
ci_to = swap_client.ci(Coins(o.coin_to)) ci_to = swap_client.ci(Coins(o.coin_to))
is_expired = o.expire_at <= now is_expired = o.expire_at <= now
amount_negotiable = "Yes" if o.amount_negotiable else "No" amount_negotiable = "Yes" if o.amount_negotiable else "No"
formatted_created_at = format_timestamp(o.created_at, with_ago=True)
formatted_expired_at = format_timestamp(o.expire_at, with_ago=False, is_expired=True)
tla_from = ci_from.ticker()
tla_to = ci_to.ticker()
amount_to: int = o.amount_to
if amount_to is None:
amount_to = (o.amount_from * o.rate) // ci_from.COIN()
formatted_offers.append(( formatted_offers.append((
formatted_created_at, format_timestamp(o.created_at),
o.offer_id.hex(), o.offer_id.hex(),
ci_from.coin_name(), ci_from.coin_name(),
ci_to.coin_name(), ci_to.coin_name(),
ci_from.format_amount(o.amount_from), ci_from.format_amount(o.amount_from),
ci_to.format_amount(amount_to), ci_to.format_amount((o.amount_from * o.rate) // ci_from.COIN()),
ci_to.format_amount(o.rate), ci_to.format_amount(o.rate),
'Public' if o.addr_to == swap_client.network_addr else o.addr_to, 'Public' if o.addr_to == swap_client.network_addr else o.addr_to,
o.addr_from, o.addr_from,
@@ -805,12 +741,8 @@ def page_offers(self, url_split, post_string, sent=False):
ci_from.format_amount(completed_amount), ci_from.format_amount(completed_amount),
is_expired, is_expired,
o.active_ind, o.active_ind,
formatted_expired_at,
strSwapDesc(o.swap_type), strSwapDesc(o.swap_type),
amount_negotiable, amount_negotiable))
tla_from,
tla_to
))
coins_from, coins_to = listAvailableCoins(swap_client, split_from=True) coins_from, coins_to = listAvailableCoins(swap_client, split_from=True)
@@ -819,43 +751,14 @@ def page_offers(self, url_split, post_string, sent=False):
chart_api_key_enc = swap_client.settings.get('chart_api_key_enc', '') chart_api_key_enc = swap_client.settings.get('chart_api_key_enc', '')
chart_api_key = default_chart_api_key if chart_api_key_enc == '' else bytes.fromhex(chart_api_key_enc).decode('utf-8') chart_api_key = default_chart_api_key if chart_api_key_enc == '' else bytes.fromhex(chart_api_key_enc).decode('utf-8')
coingecko_api_key = swap_client.settings.get('coingecko_api_key', '')
if coingecko_api_key == '':
coingecko_api_key_enc = swap_client.settings.get('coingecko_api_key_enc', '')
coingecko_api_key = default_coingecko_api_key if coingecko_api_key_enc == '' else bytes.fromhex(coingecko_api_key_enc).decode('utf-8')
offers_count = len(formatted_offers)
enabled_chart_coins = []
enabled_chart_coins_setting = swap_client.settings.get('enabled_chart_coins', '')
if enabled_chart_coins_setting.lower() == 'all':
enabled_chart_coins = known_chart_coins
elif enabled_chart_coins_setting.strip() == '':
for coin_id in swap_client.coin_clients:
if not swap_client.isCoinActive(coin_id):
continue
try:
enabled_ticker = swap_client.ci(coin_id).ticker_mainnet()
except Exception:
continue
if enabled_ticker not in enabled_chart_coins and enabled_ticker in known_chart_coins:
enabled_chart_coins.append(enabled_ticker)
else:
for ticker in enabled_chart_coins_setting.split(','):
upcased_ticker = ticker.strip().upper()
if upcased_ticker not in enabled_chart_coins and upcased_ticker in known_chart_coins:
enabled_chart_coins.append(upcased_ticker)
template = server.env.get_template('offers.html') template = server.env.get_template('offers.html')
return self.render_template(template, { return self.render_template(template, {
'page_type': 'Your Offers' if sent else 'Network Order Book', 'page_type': 'Your Offers' if sent else 'Network Order Book',
'page_button': 'hidden' if sent or offers_count <= 30 else '', 'page_button': 'hidden' if sent else '',
'page_type_description': 'Your entire offer history.' if sent else 'Consult available offers in the order book and initiate a coin swap.', 'page_type_description': 'Your entire offer history.' if sent else 'Consult available offers in the order book and initiate a coin swap.',
'messages': messages, 'messages': messages,
'show_chart': False if sent else swap_client.settings.get('show_chart', True), 'show_chart': False if sent else swap_client.settings.get('show_chart', True),
'chart_api_key': chart_api_key, 'chart_api_key': chart_api_key,
'coingecko_api_key': coingecko_api_key,
'coins_from': coins_from, 'coins_from': coins_from,
'coins': coins_to, 'coins': coins_to,
'messages': messages, 'messages': messages,
@@ -863,8 +766,4 @@ def page_offers(self, url_split, post_string, sent=False):
'offers': formatted_offers, 'offers': formatted_offers,
'summary': summary, 'summary': summary,
'sent_offers': sent, 'sent_offers': sent,
'offers_count': offers_count,
'tla_from': tla_from,
'tla_to': tla_to,
'enabled_chart_coins': enabled_chart_coins,
}) })

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2022-2024 tecnovert # Copyright (c) 2022-2023 tecnovert
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php. # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@@ -45,8 +45,6 @@ def page_settings(self, url_split, post_string):
data = { data = {
'show_chart': toBool(get_data_entry(form_data, 'showchart')), 'show_chart': toBool(get_data_entry(form_data, 'showchart')),
'chart_api_key': html.unescape(get_data_entry_or(form_data, 'chartapikey', '')), 'chart_api_key': html.unescape(get_data_entry_or(form_data, 'chartapikey', '')),
'coingecko_api_key': html.unescape(get_data_entry_or(form_data, 'coingeckoapikey', '')),
'enabled_chart_coins': get_data_entry_or(form_data, 'enabledchartcoins', ''),
} }
swap_client.editGeneralSettings(data) swap_client.editGeneralSettings(data)
elif have_data_entry(form_data, 'apply_tor'): elif have_data_entry(form_data, 'apply_tor'):
@@ -132,17 +130,9 @@ def page_settings(self, url_split, post_string):
chart_api_key = html.escape(bytes.fromhex(swap_client.settings.get('chart_api_key_enc', '')).decode('utf-8')) chart_api_key = html.escape(bytes.fromhex(swap_client.settings.get('chart_api_key_enc', '')).decode('utf-8'))
else: else:
chart_api_key = swap_client.settings.get('chart_api_key', '') chart_api_key = swap_client.settings.get('chart_api_key', '')
if 'coingecko_api_key_enc' in swap_client.settings:
coingecko_api_key = html.escape(bytes.fromhex(swap_client.settings.get('coingecko_api_key_enc', '')).decode('utf-8'))
else:
coingecko_api_key = swap_client.settings.get('coingecko_api_key', '')
chart_settings = { chart_settings = {
'show_chart': swap_client.settings.get('show_chart', True), 'show_chart': swap_client.settings.get('show_chart', True),
'chart_api_key': chart_api_key, 'chart_api_key': chart_api_key,
'coingecko_api_key': coingecko_api_key,
'enabled_chart_coins': swap_client.settings.get('enabled_chart_coins', ''),
} }
tor_control_password = '' if swap_client.tor_control_password is None else swap_client.tor_control_password tor_control_password = '' if swap_client.tor_control_password is None else swap_client.tor_control_password

View File

@@ -133,36 +133,23 @@ def page_wallet(self, url_split, post_string):
page_data = {} page_data = {}
messages = [] messages = []
err_messages = [] err_messages = []
show_utxo_groups: bool = False show_utxo_groups = False
withdrawal_successful: bool = False
force_refresh: bool = False
form_data = self.checkForm(post_string, 'wallet', err_messages) form_data = self.checkForm(post_string, 'wallet', err_messages)
if form_data: if form_data:
cid = str(int(coin_id)) cid = str(int(coin_id))
estimate_fee: bool = have_data_entry(form_data, 'estfee_' + cid) if bytes('newaddr_' + cid, 'utf-8') in form_data:
withdraw: bool = have_data_entry(form_data, 'withdraw_' + cid)
if have_data_entry(form_data, 'newaddr_' + cid):
swap_client.cacheNewAddressForCoin(coin_id) swap_client.cacheNewAddressForCoin(coin_id)
elif have_data_entry(form_data, 'forcerefresh'): elif bytes('newmwebaddr_' + cid, 'utf-8') in form_data:
force_refresh = True
elif have_data_entry(form_data, 'newmwebaddr_' + cid):
swap_client.cacheNewStealthAddressForCoin(coin_id) swap_client.cacheNewStealthAddressForCoin(coin_id)
elif have_data_entry(form_data, 'reseed_' + cid): elif bytes('reseed_' + cid, 'utf-8') in form_data:
try: try:
swap_client.reseedWallet(coin_id) swap_client.reseedWallet(coin_id)
messages.append('Reseed complete ' + str(coin_id)) messages.append('Reseed complete ' + str(coin_id))
except Exception as ex: except Exception as ex:
err_messages.append('Reseed failed ' + str(ex)) err_messages.append('Reseed failed ' + str(ex))
swap_client.updateWalletsInfo(True, coin_id) swap_client.updateWalletsInfo(True, coin_id)
elif withdraw or estimate_fee: elif bytes('withdraw_' + cid, 'utf-8') in form_data:
subfee = True if have_data_entry(form_data, 'subfee_' + cid) else False
page_data['wd_subfee_' + cid] = subfee
sweepall = True if have_data_entry(form_data, 'sweepall_' + cid) else False
page_data['wd_sweepall_' + cid] = sweepall
value = None
if not sweepall:
try: try:
value = form_data[bytes('amt_' + cid, 'utf-8')][0].decode('utf-8') value = form_data[bytes('amt_' + cid, 'utf-8')][0].decode('utf-8')
page_data['wd_value_' + cid] = value page_data['wd_value_' + cid] = value
@@ -174,12 +161,8 @@ def page_wallet(self, url_split, post_string):
except Exception as e: except Exception as e:
err_messages.append('Missing address') err_messages.append('Missing address')
if estimate_fee and withdraw: subfee = True if bytes('subfee_' + cid, 'utf-8') in form_data else False
err_messages.append('Estimate fee and withdraw can\'t be used together.') page_data['wd_subfee_' + cid] = subfee
if estimate_fee and coin_id not in (Coins.XMR, ):
ci = swap_client.ci(coin_id)
ticker: str = ci.ticker()
err_messages.append(f'Estimate fee unavailable for {ticker}.')
if coin_id == Coins.PART: if coin_id == Coins.PART:
try: try:
@@ -196,9 +179,9 @@ def page_wallet(self, url_split, post_string):
except Exception as e: except Exception as e:
err_messages.append('Missing type') err_messages.append('Missing type')
if len(err_messages) == 0: if len(messages) == 0:
ci = swap_client.ci(coin_id) ci = swap_client.ci(coin_id)
ticker: str = ci.ticker() ticker = ci.ticker()
try: try:
if coin_id == Coins.PART: if coin_id == Coins.PART:
txid = swap_client.withdrawParticl(type_from, type_to, value, address, subfee) txid = swap_client.withdrawParticl(type_from, type_to, value, address, subfee)
@@ -206,32 +189,12 @@ def page_wallet(self, url_split, post_string):
elif coin_id == Coins.LTC: elif coin_id == Coins.LTC:
txid = swap_client.withdrawLTC(type_from, value, address, subfee) txid = swap_client.withdrawLTC(type_from, value, address, subfee)
messages.append('Withdrew {} {} (from {}) to address {}<br/>In txid: {}'.format(value, ticker, type_from, address, txid)) messages.append('Withdrew {} {} (from {}) to address {}<br/>In txid: {}'.format(value, ticker, type_from, address, txid))
elif coin_id == Coins.XMR:
if estimate_fee:
fee_estimate = ci.estimateFee(value, address, sweepall)
suffix = 's' if fee_estimate['num_txns'] > 1 else ''
sum_fees = ci.format_amount(fee_estimate['sum_fee'])
value_str = ci.format_amount(fee_estimate['sum_amount'])
messages.append(f'Estimated fee for {value_str} {ticker} to address {address}: {sum_fees} in {fee_estimate["num_txns"]} transaction{suffix}.')
page_data['fee_estimate'] = fee_estimate
else:
txid = swap_client.withdrawCoin(coin_id, value, address, sweepall)
if sweepall:
messages.append('Swept all {} to address {}<br/>In txid: {}'.format(ticker, address, txid))
else:
messages.append('Withdrew {} {} to address {}<br/>In txid: {}'.format(value, ticker, address, txid))
messages.append('Note: The wallet balance can take a while to update.')
else: else:
txid = swap_client.withdrawCoin(coin_id, value, address, subfee) txid = swap_client.withdrawCoin(coin_id, value, address, subfee)
messages.append('Withdrew {} {} to address {}<br/>In txid: {}'.format(value, ticker, address, txid)) messages.append('Withdrew {} {} to address {}<br/>In txid: {}'.format(value, ticker, address, txid))
if not estimate_fee:
withdrawal_successful = True
except Exception as e: except Exception as e:
if swap_client.debug is True:
swap_client.log.error(traceback.format_exc())
err_messages.append(str(e)) err_messages.append(str(e))
if not estimate_fee: swap_client.updateWalletsInfo(True, coin_id)
swap_client.updateWalletsInfo(True, only_coin=coin_id)
elif have_data_entry(form_data, 'showutxogroups'): elif have_data_entry(form_data, 'showutxogroups'):
show_utxo_groups = True show_utxo_groups = True
elif have_data_entry(form_data, 'create_utxo'): elif have_data_entry(form_data, 'create_utxo'):
@@ -241,6 +204,7 @@ def page_wallet(self, url_split, post_string):
page_data['utxo_value'] = value page_data['utxo_value'] = value
ci = swap_client.ci(coin_id) ci = swap_client.ci(coin_id)
value_sats = ci.make_int(value) value_sats = ci.make_int(value)
txid, address = ci.createUTXO(value_sats) txid, address = ci.createUTXO(value_sats)
@@ -250,7 +214,7 @@ def page_wallet(self, url_split, post_string):
if swap_client.debug is True: if swap_client.debug is True:
swap_client.log.error(traceback.format_exc()) swap_client.log.error(traceback.format_exc())
swap_client.updateWalletsInfo(force_refresh, only_coin=coin_id, wait_for_complete=True) swap_client.updateWalletsInfo(only_coin=coin_id, wait_for_complete=True)
wallets = swap_client.getCachedWalletsInfo({'coin_id': coin_id}) wallets = swap_client.getCachedWalletsInfo({'coin_id': coin_id})
for k in wallets.keys(): for k in wallets.keys():
w = wallets[k] w = wallets[k]
@@ -291,21 +255,14 @@ def page_wallet(self, url_split, post_string):
if 'wd_type_to_' + cid in page_data: if 'wd_type_to_' + cid in page_data:
wallet_data['wd_type_to'] = page_data['wd_type_to_' + cid] wallet_data['wd_type_to'] = page_data['wd_type_to_' + cid]
if 'utxo_value' in page_data:
wallet_data['utxo_value'] = page_data['utxo_value']
if not withdrawal_successful:
if 'wd_value_' + cid in page_data: if 'wd_value_' + cid in page_data:
wallet_data['wd_value'] = page_data['wd_value_' + cid] wallet_data['wd_value'] = page_data['wd_value_' + cid]
if 'wd_address_' + cid in page_data: if 'wd_address_' + cid in page_data:
wallet_data['wd_address'] = page_data['wd_address_' + cid] wallet_data['wd_address'] = page_data['wd_address_' + cid]
if 'wd_subfee_' + cid in page_data: if 'wd_subfee_' + cid in page_data:
wallet_data['wd_subfee'] = page_data['wd_subfee_' + cid] wallet_data['wd_subfee'] = page_data['wd_subfee_' + cid]
if 'wd_sweepall_' + cid in page_data: if 'utxo_value' in page_data:
wallet_data['wd_sweepall'] = page_data['wd_sweepall_' + cid] wallet_data['utxo_value'] = page_data['utxo_value']
if 'fee_estimate' in page_data:
wallet_data['est_fee'] = ci.format_amount(page_data['fee_estimate']['sum_fee'])
wallet_data['fee_rate'] = ci.format_amount(page_data['fee_estimate']['sum_fee'] * 1000 // page_data['fee_estimate']['sum_weight'])
if show_utxo_groups: if show_utxo_groups:
utxo_groups = '' utxo_groups = ''

View File

@@ -31,9 +31,8 @@ from basicswap.basicswap_util import (
from basicswap.protocols.xmr_swap_1 import getChainBSplitKey, getChainBRemoteSplitKey from basicswap.protocols.xmr_swap_1 import getChainBSplitKey, getChainBRemoteSplitKey
PAGE_LIMIT = 25 PAGE_LIMIT = 50
invalid_coins_from = [] invalid_coins_from = []
known_chart_coins = ['BTC', 'PART', 'XMR', 'LTC', 'FIRO', 'DASH', 'PIVX', 'DOGE', 'ETH', 'DCR', 'ZANO', 'WOW']
def tickerToCoinId(ticker): def tickerToCoinId(ticker):
@@ -163,14 +162,12 @@ def describeBid(swap_client, bid, xmr_swap, offer, xmr_offer, bid_events, edit_b
ci_follower = ci_from if reverse_bid else ci_to ci_follower = ci_from if reverse_bid else ci_to
bid_amount: int = bid.amount bid_amount: int = bid.amount
bid_amount_to: int = bid.amount_to
bid_rate: int = offer.rate if bid.rate is None else bid.rate bid_rate: int = offer.rate if bid.rate is None else bid.rate
initiator_role: str = 'offerer' # Leader initiator_role: str = 'offerer' # Leader
participant_role: str = 'bidder' # Follower participant_role: str = 'bidder' # Follower
if reverse_bid: if reverse_bid:
bid_amount = bid.amount_to bid_amount = bid.amount_to
bid_amount_to = bid.amount
bid_rate = ci_from.make_int(bid.amount / bid.amount_to, r=1) bid_rate = ci_from.make_int(bid.amount / bid.amount_to, r=1)
initiator_role = 'bidder' initiator_role = 'bidder'
participant_role = 'offerer' participant_role = 'offerer'
@@ -262,7 +259,7 @@ def describeBid(swap_client, bid, xmr_swap, offer, xmr_offer, bid_events, edit_b
'coin_from': ci_from.coin_name(), 'coin_from': ci_from.coin_name(),
'coin_to': ci_to.coin_name(), 'coin_to': ci_to.coin_name(),
'amt_from': ci_from.format_amount(bid_amount), 'amt_from': ci_from.format_amount(bid_amount),
'amt_to': ci_to.format_amount(bid_amount_to), 'amt_to': ci_to.format_amount((bid_amount * bid_rate) // ci_from.COIN()),
'bid_rate': ci_to.format_amount(bid_rate), 'bid_rate': ci_to.format_amount(bid_rate),
'ticker_from': ci_from.ticker(), 'ticker_from': ci_from.ticker(),
'ticker_to': ci_to.ticker(), 'ticker_to': ci_to.ticker(),

View File

@@ -67,7 +67,6 @@ def dumpje(jin):
def SerialiseNum(n: int) -> bytes: def SerialiseNum(n: int) -> bytes:
# For script
if n == 0: if n == 0:
return bytes((0x00,)) return bytes((0x00,))
if n > 0 and n <= 16: if n > 0 and n <= 16:
@@ -86,7 +85,6 @@ def SerialiseNum(n: int) -> bytes:
def DeserialiseNum(b: bytes, o: int = 0) -> int: def DeserialiseNum(b: bytes, o: int = 0) -> int:
# For script
if b[o] == 0: if b[o] == 0:
return 0 return 0
if b[o] > 0x50 and b[o] <= 0x50 + 16: if b[o] > 0x50 and b[o] <= 0x50 + 16:
@@ -108,7 +106,7 @@ def float_to_str(f: float) -> str:
return format(d1, 'f') return format(d1, 'f')
def make_int(v, scale: int = 8, r: int = 0) -> int: # r = 0, no rounding (fail), r > 0 round off, r < 0 floor def make_int(v, scale: int = 8, r: int = 0) -> int: # r = 0, no rounding, fail, r > 0 round up, r < 0 floor
if isinstance(v, float): if isinstance(v, float):
v = float_to_str(v) v = float_to_str(v)
elif isinstance(v, int): elif isinstance(v, int):
@@ -134,7 +132,7 @@ def make_int(v, scale: int = 8, r: int = 0) -> int: # r = 0, no rounding (fail)
if r == 0: if r == 0:
raise ValueError('Mantissa too long') raise ValueError('Mantissa too long')
if r > 0: if r > 0:
# Round off # Round up
if int(c) > 4: if int(c) > 4:
rv += 1 rv += 1
break break

View File

@@ -1,11 +1,12 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2022-2024 tecnovert # Copyright (c) 2022-2023 tecnovert
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php. # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
import hashlib
from basicswap.contrib.segwit_addr import bech32_decode, convertbits, bech32_encode from basicswap.contrib.segwit_addr import bech32_decode, convertbits, bech32_encode
from basicswap.util.crypto import ripemd160, sha256 from basicswap.util.crypto import ripemd160
__b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' __b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
@@ -67,7 +68,7 @@ def encodeStealthAddress(prefix_byte: int, scan_pubkey: bytes, spend_pubkey: byt
data += bytes((0x00,)) # num prefix bits data += bytes((0x00,)) # num prefix bits
b = bytes((prefix_byte,)) + data b = bytes((prefix_byte,)) + data
b += sha256(sha256(b))[:4] b += hashlib.sha256(hashlib.sha256(b).digest()).digest()[:4]
return b58encode(b) return b58encode(b)
@@ -82,15 +83,16 @@ def toWIF(prefix_byte: int, b: bytes, compressed: bool = True) -> str:
b = bytes((prefix_byte,)) + b b = bytes((prefix_byte,)) + b
if compressed: if compressed:
b += bytes((0x01,)) b += bytes((0x01,))
b += sha256(sha256(b))[:4] b += hashlib.sha256(hashlib.sha256(b).digest()).digest()[:4]
return b58encode(b) return b58encode(b)
def getKeyID(key_data: bytes) -> bytes: def getKeyID(key_data: bytes) -> bytes:
return ripemd160(sha256(key_data)) sha256_hash = hashlib.sha256(key_data).digest()
return ripemd160(sha256_hash)
def bech32Decode(hrp: str, addr: str) -> bytes: def bech32Decode(hrp, addr):
hrpgot, data = bech32_decode(addr) hrpgot, data = bech32_decode(addr)
if hrpgot != hrp: if hrpgot != hrp:
return None return None
@@ -100,26 +102,25 @@ def bech32Decode(hrp: str, addr: str) -> bytes:
return bytes(decoded) return bytes(decoded)
def bech32Encode(hrp: str, data: bytes) -> str: def bech32Encode(hrp, data):
ret = bech32_encode(hrp, convertbits(data, 8, 5)) ret = bech32_encode(hrp, convertbits(data, 8, 5))
if bech32Decode(hrp, ret) is None: if bech32Decode(hrp, ret) is None:
return None return None
return ret return ret
def decodeAddress(address: str) -> bytes: def decodeAddress(address_str: str):
addr_data = b58decode(address) b58_addr = b58decode(address_str)
if addr_data is None: if b58_addr is not None:
address = b58_addr[:-4]
checksum = b58_addr[-4:]
assert (hashlib.sha256(hashlib.sha256(address).digest()).digest()[:4] == checksum), 'Checksum mismatch'
return b58_addr[:-4]
return None return None
prefixed_data = addr_data[:-4]
checksum = addr_data[-4:]
if sha256(sha256(prefixed_data))[:4] != checksum:
raise ValueError('Checksum mismatch')
return prefixed_data
def encodeAddress(address: bytes) -> str: def encodeAddress(address: bytes) -> str:
checksum = sha256(sha256(address)) checksum = hashlib.sha256(hashlib.sha256(address).digest()).digest()
return b58encode(address + checksum[0:4]) return b58encode(address + checksum[0:4])

View File

@@ -1,41 +1,23 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2022-2024 tecnovert # Copyright (c) 2022-2023 tecnovert
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php. # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
from basicswap.contrib.blake256.blake256 import blake_hash from Crypto.Hash import RIPEMD160, SHA256 # pycryptodome
from Crypto.Hash import HMAC, RIPEMD160, SHA256, SHA512 # pycryptodome
def sha256(data: bytes) -> bytes: def sha256(data):
h = SHA256.new() h = SHA256.new()
h.update(data) h.update(data)
return h.digest() return h.digest()
def sha512(data: bytes) -> bytes: def ripemd160(data):
h = SHA512.new()
h.update(data)
return h.digest()
def ripemd160(data: bytes) -> bytes:
h = RIPEMD160.new() h = RIPEMD160.new()
h.update(data) h.update(data)
return h.digest() return h.digest()
def blake256(data: bytes) -> bytes: def hash160(s):
return blake_hash(data) return ripemd160(sha256(s))
def hash160(data: bytes) -> bytes:
return ripemd160(sha256(data))
def hmac_sha512(secret: bytes, data: bytes) -> bytes:
h = HMAC.new(secret, digestmod=SHA512)
h.update(data)
return h.digest()

View File

@@ -1,116 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2024 tecnovert
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
from .crypto import blake256, hash160, hmac_sha512, ripemd160
from coincurve.keys import (
PrivateKey,
PublicKey)
def BIP32Hash(chaincode: bytes, child_no: int, key_data_type: int, keydata: bytes):
return hmac_sha512(chaincode, key_data_type.to_bytes(1, 'big') + keydata + child_no.to_bytes(4, 'big'))
def hash160_dcr(data: bytes) -> bytes:
return ripemd160(blake256(data))
class ExtKeyPair():
__slots__ = ('_depth', '_fingerprint', '_child_no', '_chaincode', '_key', '_pubkey', 'hash_func')
def __init__(self, coin_type=1):
if coin_type == 4:
self.hash_func = hash160_dcr
else:
self.hash_func = hash160
def set_seed(self, seed: bytes) -> None:
hashout: bytes = hmac_sha512(b'Bitcoin seed', seed)
self._key = hashout[:32]
self._pubkey = None
self._chaincode = hashout[32:]
self._depth = 0
self._child_no = 0
self._fingerprint = b'\0' * 4
def has_key(self) -> bool:
return False if self._key is None else True
def neuter(self) -> None:
if self._key is None:
raise ValueError('Already neutered')
self._pubkey = PublicKey.from_secret(self._key).format()
self._key = None
def derive(self, child_no: int):
out = ExtKeyPair()
out._depth = self._depth + 1
out._child_no = child_no
if (child_no >> 31) == 0:
if self._key:
K = PublicKey.from_secret(self._key)
k_encoded = K.format()
else:
K = PublicKey(self._pubkey)
k_encoded = self._pubkey
out._fingerprint = self.hash_func(k_encoded)[:4]
new_hash = BIP32Hash(self._chaincode, child_no, k_encoded[0], k_encoded[1:])
out._chaincode = new_hash[32:]
if self._key:
k = PrivateKey(self._key)
k.add(new_hash[:32], update=True)
out._key = k.secret
out._pubkey = None
else:
K.add(new_hash[:32], update=True)
out._key = None
out._pubkey = K.format()
else:
k = PrivateKey(self._key)
out._fingerprint = self.hash_func(self._pubkey if self._pubkey else PublicKey.from_secret(self._key).format())[:4]
new_hash = BIP32Hash(self._chaincode, child_no, 0, self._key)
out._chaincode = new_hash[32:]
k.add(new_hash[:32], update=True)
out._key = k.secret
out._pubkey = None
out.hash_func = self.hash_func
return out
def encode_v(self) -> bytes:
return self._depth.to_bytes(1, 'big') + \
self._fingerprint + \
self._child_no.to_bytes(4, 'big') + \
self._chaincode + \
b'\x00' + \
self._key
def encode_p(self) -> bytes:
pubkey = PublicKey.from_secret(self._key).format() if self._pubkey is None else self._pubkey
return self._depth.to_bytes(1, 'big') + \
self._fingerprint + \
self._child_no.to_bytes(4, 'big') + \
self._chaincode + \
pubkey
def decode(self, data: bytes) -> None:
if len(data) != 74:
raise ValueError('Unexpected extkey length')
self._depth = data[0]
self._fingerprint = data[1:5]
self._child_no = int.from_bytes(data[5:9], 'big')
self._chaincode = data[9:41]
if data[41] == 0:
self._key = data[42:]
self._pubkey = None
else:
self._key = None
self._pubkey = data[41:]

View File

@@ -1,51 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2024 tecnovert
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
def decode_compactsize(b: bytes, offset: int = 0) -> (int, int):
i = b[offset]
if i < 0xfd:
return i, 1
offset += 1
if i == 0xfd:
return int.from_bytes(b[offset: offset + 2]), 3
if i == 0xfe:
return int.from_bytes(b[offset: offset + 4]), 5
# 0xff
return int.from_bytes(b[offset: offset + 8]), 9
def encode_compactsize(i: int) -> bytes:
if i < 0xfd:
return bytes((i,))
if i <= 0xffff:
return bytes((0xfd,)) + i.to_bytes(2, 'little')
if i <= 0xffffffff:
return bytes((0xfe,)) + i.to_bytes(4, 'little')
return bytes((0xff,)) + i.to_bytes(8, 'little')
def decode_varint(b: bytes, offset: int = 0) -> (int, int):
i: int = 0
num_bytes: int = 0
while True:
c = b[offset + num_bytes]
i += (c & 0x7F) << (num_bytes * 7)
num_bytes += 1
if not c & 0x80:
break
if num_bytes > 8:
raise ValueError('Too many bytes')
return i, num_bytes
def encode_varint(i: int) -> bytes:
b = bytearray()
while i > 0x7F:
b += bytes(((i & 0x7F) | 0x80,))
i = (i >> 7)
b += bytes((i,))
return b

View File

@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import basicswap.contrib.Keccak as Keccak import basicswap.contrib.Keccak as Keccak
from basicswap.util.integer import encode_varint
from .contrib.MoneroPy.base58 import encode as xmr_b58encode from .contrib.MoneroPy.base58 import encode as xmr_b58encode
@@ -10,9 +9,8 @@ def cn_fast_hash(s):
return k.Keccak((len(s) * 8, s.hex()), 1088, 512, 32 * 8, False).lower() # r = bitrate = 1088, c = capacity, n = output length in bits return k.Keccak((len(s) * 8, s.hex()), 1088, 512, 32 * 8, False).lower() # r = bitrate = 1088, c = capacity, n = output length in bits
def encode_address(view_point: bytes, spend_point: bytes, version=18) -> str: def encode_address(view_point, spend_point, version=18):
prefix_bytes = version if isinstance(version, bytes) else encode_varint(version) buf = bytes((version,)) + spend_point + view_point
buf = prefix_bytes + spend_point + view_point
h = cn_fast_hash(buf) h = cn_fast_hash(buf)
buf = buf + bytes.fromhex(h[0: 8]) buf = buf + bytes.fromhex(h[0: 8])

View File

@@ -5,71 +5,65 @@
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php. # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
import contextlib
import gnupg
import hashlib
import json
import logging
import mmap
import os import os
import platform import sys
import random import json
import time
import mmap
import stat
import gnupg
import socks
import shutil import shutil
import signal import signal
import socket import socket
import socks import hashlib
import stat
import sys
import tarfile import tarfile
import threading
import time
import urllib.parse
import zipfile import zipfile
import logging
import platform
import contextlib
import urllib.parse
from urllib.error import ContentTooShortError from urllib.error import ContentTooShortError
from urllib.parse import _splittype
from urllib.request import Request, urlopen from urllib.request import Request, urlopen
from urllib.parse import _splittype
import basicswap.config as cfg import basicswap.config as cfg
from basicswap import __version__
from basicswap.base import getaddrinfo_tor from basicswap.base import getaddrinfo_tor
from basicswap.basicswap import BasicSwap from basicswap.basicswap import BasicSwap
from basicswap.chainparams import Coins from basicswap.chainparams import Coins
from basicswap.contrib.rpcauth import generate_salt, password_to_hmac
from basicswap import __version__
from basicswap.ui.util import getCoinName from basicswap.ui.util import getCoinName
from basicswap.util import toBool from basicswap.util import toBool
from basicswap.util.rfc2440 import rfc2440_hash_password from basicswap.util.rfc2440 import rfc2440_hash_password
from basicswap.contrib.rpcauth import generate_salt, password_to_hmac
from bin.basicswap_run import startDaemon, startXmrWalletDaemon from bin.basicswap_run import startDaemon, startXmrWalletDaemon
PARTICL_VERSION = os.getenv('PARTICL_VERSION', '23.2.7.0') PARTICL_VERSION = os.getenv('PARTICL_VERSION', '23.2.7.0')
PARTICL_VERSION_TAG = os.getenv('PARTICL_VERSION_TAG', '') PARTICL_VERSION_TAG = os.getenv('PARTICL_VERSION_TAG', '')
PARTICL_LINUX_EXTRA = os.getenv('PARTICL_LINUX_EXTRA', 'nousb') PARTICL_LINUX_EXTRA = os.getenv('PARTICL_LINUX_EXTRA', 'nousb')
LITECOIN_VERSION = os.getenv('LITECOIN_VERSION', '0.21.3') LITECOIN_VERSION = os.getenv('LITECOIN_VERSION', '0.21.2.2')
LITECOIN_VERSION_TAG = os.getenv('LITECOIN_VERSION_TAG', '') LITECOIN_VERSION_TAG = os.getenv('LITECOIN_VERSION_TAG', '')
BITCOIN_VERSION = os.getenv('BITCOIN_VERSION', '26.0') BITCOIN_VERSION = os.getenv('BITCOIN_VERSION', '26.0')
BITCOIN_VERSION_TAG = os.getenv('BITCOIN_VERSION_TAG', '') BITCOIN_VERSION_TAG = os.getenv('BITCOIN_VERSION_TAG', '')
MONERO_VERSION = os.getenv('MONERO_VERSION', '0.18.3.3') MONERO_VERSION = os.getenv('MONERO_VERSION', '0.18.3.1')
MONERO_VERSION_TAG = os.getenv('MONERO_VERSION_TAG', '') MONERO_VERSION_TAG = os.getenv('MONERO_VERSION_TAG', '')
XMR_SITE_COMMIT = 'd00169a6decd9470ebdf6a75e3351df4ebcd260a' # Lock hashes.txt to monero version XMR_SITE_COMMIT = '1bdb0d456943a224a4d6241b1bb713172e5fa29f' # Lock hashes.txt to monero version
PIVX_VERSION = os.getenv('PIVX_VERSION', '5.6.1') PIVX_VERSION = os.getenv('PIVX_VERSION', '5.5.0')
PIVX_VERSION_TAG = os.getenv('PIVX_VERSION_TAG', '') PIVX_VERSION_TAG = os.getenv('PIVX_VERSION_TAG', '')
DASH_VERSION = os.getenv('DASH_VERSION', '20.0.2') DASH_VERSION = os.getenv('DASH_VERSION', '20.0.2')
DASH_VERSION_TAG = os.getenv('DASH_VERSION_TAG', '') DASH_VERSION_TAG = os.getenv('DASH_VERSION_TAG', '')
FIRO_VERSION = os.getenv('FIRO_VERSION', '0.14.13.2') FIRO_VERSION = os.getenv('FIRO_VERSION', '0.14.13.1')
FIRO_VERSION_TAG = os.getenv('FIRO_VERSION_TAG', '') FIRO_VERSION_TAG = os.getenv('FIRO_VERSION_TAG', '')
NAV_VERSION = os.getenv('NAV_VERSION', '7.0.3') NAV_VERSION = os.getenv('NAV_VERSION', '7.0.3')
NAV_VERSION_TAG = os.getenv('NAV_VERSION_TAG', '') 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', '')
GUIX_SSL_CERT_DIR = None GUIX_SSL_CERT_DIR = None
ADD_PUBKEY_URL = os.getenv('ADD_PUBKEY_URL', '') ADD_PUBKEY_URL = os.getenv('ADD_PUBKEY_URL', '')
@@ -89,12 +83,10 @@ known_coins = {
'dash': (DASH_VERSION, DASH_VERSION_TAG, ('pasta',)), 'dash': (DASH_VERSION, DASH_VERSION_TAG, ('pasta',)),
'firo': (FIRO_VERSION, FIRO_VERSION_TAG, ('reuben',)), 'firo': (FIRO_VERSION, FIRO_VERSION_TAG, ('reuben',)),
'navcoin': (NAV_VERSION, NAV_VERSION_TAG, ('nav_builder',)), 'navcoin': (NAV_VERSION, NAV_VERSION_TAG, ('nav_builder',)),
'decred': (DCR_VERSION, DCR_VERSION_TAG, ('decred_release',)),
} }
disabled_coins = [ disabled_coins = [
'navcoin', 'navcoin',
'namecoin', # Needs update
] ]
expected_key_ids = { expected_key_ids = {
@@ -104,11 +96,10 @@ expected_key_ids = {
'JeremyRand': ('2DBE339E29F6294C',), 'JeremyRand': ('2DBE339E29F6294C',),
'binaryfate': ('F0AF4D462A0BDF92',), 'binaryfate': ('F0AF4D462A0BDF92',),
'davidburkett38': ('3620E9D387E55666',), 'davidburkett38': ('3620E9D387E55666',),
'fuzzbawls': ('C1ABA64407731FD9',), 'fuzzbawls': ('3BDCDA2D87A881D9',),
'pasta': ('52527BEDABE87984',), 'pasta': ('52527BEDABE87984',),
'reuben': ('1290A1D0FA7EE109',), 'reuben': ('1290A1D0FA7EE109',),
'nav_builder': ('2782262BF6E7FADB',), 'nav_builder': ('2782262BF6E7FADB',),
'decred_release': ('6D897EDF518A031D',),
} }
USE_PLATFORM = os.getenv('USE_PLATFORM', platform.system()) USE_PLATFORM = os.getenv('USE_PLATFORM', platform.system())
@@ -169,14 +160,6 @@ BTC_ONION_PORT = int(os.getenv('BTC_ONION_PORT', 8334))
BTC_RPC_USER = os.getenv('BTC_RPC_USER', '') BTC_RPC_USER = os.getenv('BTC_RPC_USER', '')
BTC_RPC_PWD = os.getenv('BTC_RPC_PWD', '') BTC_RPC_PWD = os.getenv('BTC_RPC_PWD', '')
DCR_RPC_HOST = os.getenv('DCR_RPC_HOST', '127.0.0.1')
DCR_RPC_PORT = int(os.getenv('DCR_RPC_PORT', 9109))
DCR_WALLET_RPC_HOST = os.getenv('DCR_WALLET_RPC_HOST', '127.0.0.1')
DCR_WALLET_RPC_PORT = int(os.getenv('DCR_WALLET_RPC_PORT', 9209))
DCR_WALLET_PWD = os.getenv('DCR_WALLET_PWD', random.randbytes(random.randint(14, 18)).hex())
DCR_RPC_USER = os.getenv('DCR_RPC_USER', 'user')
DCR_RPC_PWD = os.getenv('DCR_RPC_PWD', random.randbytes(random.randint(14, 18)).hex())
NMC_RPC_HOST = os.getenv('NMC_RPC_HOST', '127.0.0.1') NMC_RPC_HOST = os.getenv('NMC_RPC_HOST', '127.0.0.1')
NMC_RPC_PORT = int(os.getenv('NMC_RPC_PORT', 19698)) NMC_RPC_PORT = int(os.getenv('NMC_RPC_PORT', 19698))
@@ -372,16 +355,16 @@ def setConnectionParameters(timeout: int = 5, allow_set_tor: bool = True):
socket.setdefaulttimeout(timeout) socket.setdefaulttimeout(timeout)
def popConnectionParameters() -> None: def popConnectionParameters():
if use_tor_proxy: if use_tor_proxy:
socket.socket = default_socket socket.socket = default_socket
socket.getaddrinfo = default_socket_getaddrinfo socket.getaddrinfo = default_socket_getaddrinfo
socket.setdefaulttimeout(default_socket_timeout) socket.setdefaulttimeout(default_socket_timeout)
def downloadFile(url: str, path: str, timeout=5, resume_from=0) -> None: def downloadFile(url, path, timeout=5, resume_from=0):
logger.info(f'Downloading file {url}') logger.info('Downloading file %s', url)
logger.info(f'To {path}') logger.info('To %s', path)
try: try:
setConnectionParameters(timeout=timeout) setConnectionParameters(timeout=timeout)
urlretrieve(url, path, make_reporthook(resume_from), resume_from=resume_from) urlretrieve(url, path, make_reporthook(resume_from), resume_from=resume_from)
@@ -402,12 +385,13 @@ def importPubkeyFromUrls(gpg, pubkeyurls):
try: try:
logger.info('Importing public key from url: ' + url) logger.info('Importing public key from url: ' + url)
rv = gpg.import_keys(downloadBytes(url)) rv = gpg.import_keys(downloadBytes(url))
for key in rv.fingerprints:
gpg.trust_keys(key, 'TRUST_FULLY')
break break
except Exception as e: except Exception as e:
logging.warning('Import from url failed: %s', str(e)) logging.warning('Import from url failed: %s', str(e))
for key in rv.fingerprints:
gpg.trust_keys(key, 'TRUST_FULLY')
def testTorConnection(): def testTorConnection():
test_url = 'https://check.torproject.org/' test_url = 'https://check.torproject.org/'
@@ -535,25 +519,11 @@ def extractCore(coin, version_data, settings, bin_dir, release_path, extra_opts=
logging.warning('Unable to set file permissions: %s, for %s', str(e), out_path) logging.warning('Unable to set file permissions: %s, for %s', str(e), out_path)
return return
dir_name = 'dashcore' if coin == 'dash' else coin
if coin == 'decred':
bins = ['dcrd', 'dcrwallet']
else:
bins = [coin + 'd', coin + '-cli', coin + '-tx'] bins = [coin + 'd', coin + '-cli', coin + '-tx']
versions = version.split('.') versions = version.split('.')
dir_name = 'dashcore' if coin == 'dash' else coin
if int(versions[0]) >= 22 or int(versions[1]) >= 19: if int(versions[0]) >= 22 or int(versions[1]) >= 19:
bins.append(coin + '-wallet') bins.append(coin + '-wallet')
def get_archive_path(b):
if coin == 'pivx':
return '{}-{}/bin/{}'.format(dir_name, version, b)
elif coin == 'particl' and '_nousb-' in release_path:
return '{}-{}_nousb/bin/{}'.format(dir_name, version + version_tag, b)
elif coin == 'decred':
return '{}-{}-v{}/{}'.format(dir_name, extra_opts['arch_name'], version, b)
else:
return '{}-{}/bin/{}'.format(dir_name, version + version_tag, b)
if 'win32' in BIN_ARCH or 'win64' in BIN_ARCH: if 'win32' in BIN_ARCH or 'win64' in BIN_ARCH:
with zipfile.ZipFile(release_path) as fz: with zipfile.ZipFile(release_path) as fz:
for b in bins: for b in bins:
@@ -561,7 +531,7 @@ def extractCore(coin, version_data, settings, bin_dir, release_path, extra_opts=
out_path = os.path.join(bin_dir, b) out_path = os.path.join(bin_dir, b)
if (not os.path.exists(out_path)) or extract_core_overwrite: if (not os.path.exists(out_path)) or extract_core_overwrite:
with open(out_path, 'wb') as fout: with open(out_path, 'wb') as fout:
fout.write(fz.read(get_archive_path(b))) fout.write(fz.read('{}-{}/bin/{}'.format(dir_name, version, b)))
try: try:
os.chmod(out_path, stat.S_IRWXU | stat.S_IXGRP | stat.S_IXOTH) os.chmod(out_path, stat.S_IRWXU | stat.S_IXGRP | stat.S_IXOTH)
except Exception as e: except Exception as e:
@@ -571,7 +541,15 @@ def extractCore(coin, version_data, settings, bin_dir, release_path, extra_opts=
for b in bins: for b in bins:
out_path = os.path.join(bin_dir, b) out_path = os.path.join(bin_dir, b)
if not os.path.exists(out_path) or extract_core_overwrite: if not os.path.exists(out_path) or extract_core_overwrite:
with open(out_path, 'wb') as fout, ft.extractfile(get_archive_path(b)) as fi:
if coin == 'pivx':
filename = '{}-{}/bin/{}'.format(dir_name, version, b)
elif coin == 'particl' and '_nousb-' in release_path:
filename = '{}-{}_nousb/bin/{}'.format(dir_name, version + version_tag, b)
else:
filename = '{}-{}/bin/{}'.format(dir_name, version + version_tag, b)
with open(out_path, 'wb') as fout, ft.extractfile(filename) as fi:
fout.write(fi.read()) fout.write(fi.read())
try: try:
os.chmod(out_path, stat.S_IRWXU | stat.S_IXGRP | stat.S_IXOTH) os.chmod(out_path, stat.S_IRWXU | stat.S_IXGRP | stat.S_IXOTH)
@@ -624,39 +602,6 @@ def prepareCore(coin, version_data, settings, data_dir, extra_opts={}):
assert_path = os.path.join(bin_dir, assert_filename) assert_path = os.path.join(bin_dir, assert_filename)
if not os.path.exists(assert_path): if not os.path.exists(assert_path):
downloadFile(assert_url, assert_path) downloadFile(assert_url, assert_path)
elif coin == 'decred':
arch_name = BIN_ARCH
if USE_PLATFORM == 'Darwin':
arch_name = 'darwin-amd64'
elif USE_PLATFORM == 'Windows':
arch_name = 'windows-amd64'
else:
machine: str = platform.machine()
if 'arm' in machine:
arch_name = 'linux-arm'
else:
arch_name = 'linux-amd64'
extra_opts['arch_name'] = arch_name
release_filename = '{}-{}-{}.{}'.format(coin, version, arch_name, FILE_EXT)
release_page_url = 'https://github.com/decred/decred-binaries/releases/download/v{}'.format(version)
release_url = release_page_url + '/' + 'decred-{}-v{}.{}'.format(arch_name, version, FILE_EXT)
release_path = os.path.join(bin_dir, release_filename)
if not os.path.exists(release_path):
downloadFile(release_url, release_path)
assert_filename = 'decred-v{}-manifest.txt'.format(version)
assert_url = release_page_url + '/' + assert_filename
assert_path = os.path.join(bin_dir, assert_filename)
if not os.path.exists(assert_path):
downloadFile(assert_url, assert_path)
assert_sig_filename = assert_filename + '.asc'
assert_sig_url = assert_url + '.asc'
assert_sig_path = os.path.join(bin_dir, assert_sig_filename)
if not os.path.exists(assert_sig_path):
downloadFile(assert_sig_url, assert_sig_path)
else: else:
major_version = int(version.split('.')[0]) major_version = int(version.split('.')[0])
@@ -683,7 +628,8 @@ def prepareCore(coin, version_data, settings, data_dir, extra_opts={}):
elif coin == 'litecoin': elif coin == 'litecoin':
release_url = 'https://github.com/litecoin-project/litecoin/releases/download/v{}/{}'.format(version + version_tag, release_filename) release_url = 'https://github.com/litecoin-project/litecoin/releases/download/v{}/{}'.format(version + version_tag, release_filename)
assert_filename = '{}-core-{}-{}-build.assert'.format(coin, os_name, '.'.join(version.split('.')[:2])) assert_filename = '{}-core-{}-{}-build.assert'.format(coin, os_name, '.'.join(version.split('.')[:2]))
assert_url = 'https://raw.githubusercontent.com/litecoin-project/gitian.sigs.ltc/master/%s-%s/%s/%s' % (version, os_dir_name, signing_key_name, assert_filename) use_signing_key_name = (signing_key_name + '/' + signing_key_name) if os_name == 'win' else signing_key_name
assert_url = 'https://raw.githubusercontent.com/litecoin-project/gitian.sigs.ltc/master/%s-%s/%s/%s' % (version, os_dir_name, use_signing_key_name, assert_filename)
elif coin == 'bitcoin': elif coin == 'bitcoin':
release_url = 'https://bitcoincore.org/bin/bitcoin-core-{}/{}'.format(version, release_filename) release_url = 'https://bitcoincore.org/bin/bitcoin-core-{}/{}'.format(version, release_filename)
assert_filename = '{}-core-{}-{}-build.assert'.format(coin, os_name, '.'.join(version.split('.')[:2])) assert_filename = '{}-core-{}-{}-build.assert'.format(coin, os_name, '.'.join(version.split('.')[:2]))
@@ -777,8 +723,6 @@ def prepareCore(coin, version_data, settings, data_dir, extra_opts={}):
if coin in ('navcoin', ): if coin in ('navcoin', ):
pubkey_filename = '{}_builder.pgp'.format(coin) pubkey_filename = '{}_builder.pgp'.format(coin)
elif coin in ('decred', ):
pubkey_filename = '{}_release.pgp'.format(coin)
else: else:
pubkey_filename = '{}_{}.pgp'.format(coin, signing_key_name) pubkey_filename = '{}_{}.pgp'.format(coin, signing_key_name)
pubkeyurls = [ pubkeyurls = [
@@ -920,40 +864,6 @@ def prepareDataDir(coin, settings, chain, particl_mnemonic, extra_opts={}):
fp.write(opt_line + '\n') fp.write(opt_line + '\n')
return return
if coin == 'decred':
chainname = 'simnet' if chain == 'regtest' else chain
core_conf_path = os.path.join(data_dir, 'dcrd.conf')
if os.path.exists(core_conf_path):
exitWithError('{} exists'.format(core_conf_path))
with open(core_conf_path, 'w') as fp:
if chain != 'mainnet':
fp.write(chainname + '=1\n')
fp.write('debuglevel=debug\n')
fp.write('notls=1\n')
fp.write('rpclisten={}:{}\n'.format(core_settings['rpchost'], core_settings['rpcport']))
fp.write('rpcuser={}\n'.format(core_settings['rpcuser']))
fp.write('rpcpass={}\n'.format(core_settings['rpcpassword']))
wallet_conf_path = os.path.join(data_dir, 'dcrwallet.conf')
if os.path.exists(wallet_conf_path):
exitWithError('{} exists'.format(wallet_conf_path))
with open(wallet_conf_path, 'w') as fp:
if chain != 'mainnet':
fp.write(chainname + '=1\n')
fp.write('debuglevel=debug\n')
fp.write('noservertls=1\n')
fp.write('noclienttls=1\n')
fp.write('rpcconnect={}:{}\n'.format(core_settings['rpchost'], core_settings['rpcport']))
fp.write('rpclisten={}:{}\n'.format(core_settings['walletrpchost'], core_settings['walletrpcport']))
fp.write('username={}\n'.format(core_settings['rpcuser']))
fp.write('password={}\n'.format(core_settings['rpcpassword']))
return
core_conf_path = os.path.join(data_dir, coin + '.conf') core_conf_path = os.path.join(data_dir, coin + '.conf')
if os.path.exists(core_conf_path): if os.path.exists(core_conf_path):
exitWithError('{} exists'.format(core_conf_path)) exitWithError('{} exists'.format(core_conf_path))
@@ -996,8 +906,7 @@ def prepareDataDir(coin, settings, chain, particl_mnemonic, extra_opts={}):
fp.write('rpcauth={}:{}${}\n'.format(PART_RPC_USER, salt, password_to_hmac(salt, PART_RPC_PWD))) fp.write('rpcauth={}:{}${}\n'.format(PART_RPC_USER, salt, password_to_hmac(salt, PART_RPC_PWD)))
elif coin == 'litecoin': elif coin == 'litecoin':
fp.write('prune=4000\n') fp.write('prune=4000\n')
fp.write('blockfilterindex=0\n') fp.write('pid=litecoind.pid\n')
fp.write('peerblockfilters=0\n')
if LTC_RPC_USER != '': if LTC_RPC_USER != '':
fp.write('rpcauth={}:{}${}\n'.format(LTC_RPC_USER, salt, password_to_hmac(salt, LTC_RPC_PWD))) fp.write('rpcauth={}:{}${}\n'.format(LTC_RPC_USER, salt, password_to_hmac(salt, LTC_RPC_PWD)))
elif coin == 'bitcoin': elif coin == 'bitcoin':
@@ -1011,6 +920,7 @@ def prepareDataDir(coin, settings, chain, particl_mnemonic, extra_opts={}):
elif coin == 'pivx': elif coin == 'pivx':
params_dir = os.path.join(data_dir, 'pivx-params') params_dir = os.path.join(data_dir, 'pivx-params')
downloadPIVXParams(params_dir) downloadPIVXParams(params_dir)
fp.write('prune=4000\n')
PIVX_PARAMSDIR = os.getenv('PIVX_PARAMSDIR', '/data/pivx-params' if extra_opts.get('use_containers', False) else params_dir) PIVX_PARAMSDIR = os.getenv('PIVX_PARAMSDIR', '/data/pivx-params' if extra_opts.get('use_containers', False) else params_dir)
fp.write(f'paramsdir={PIVX_PARAMSDIR}\n') fp.write(f'paramsdir={PIVX_PARAMSDIR}\n')
if PIVX_RPC_USER != '': if PIVX_RPC_USER != '':
@@ -1217,13 +1127,13 @@ def printHelp():
def finalise_daemon(d): def finalise_daemon(d):
logging.info('Interrupting {}'.format(d.handle.pid)) logging.info('Interrupting {}'.format(d.pid))
try: try:
d.handle.send_signal(signal.CTRL_C_EVENT if os.name == 'nt' else signal.SIGINT) d.send_signal(signal.CTRL_C_EVENT if os.name == 'nt' else signal.SIGINT)
d.handle.wait(timeout=120) d.wait(timeout=120)
except Exception as e: except Exception as e:
logging.info(f'Error {e} for process {d.handle.pid}') logging.info(f'Error {e} for process {d.pid}')
for fp in [d.handle.stdout, d.handle.stderr, d.handle.stdin] + d.files: for fp in (d.stdout, d.stderr, d.stdin):
if fp: if fp:
fp.close() fp.close()
@@ -1244,7 +1154,7 @@ def test_particl_encryption(data_dir, settings, chain, use_tor_proxy):
if coin_settings['manage_daemon']: if coin_settings['manage_daemon']:
filename = coin_name + 'd' + ('.exe' if os.name == 'nt' else '') filename = coin_name + 'd' + ('.exe' if os.name == 'nt' else '')
daemons.append(startDaemon(coin_settings['datadir'], coin_settings['bindir'], filename, daemon_args)) daemons.append(startDaemon(coin_settings['datadir'], coin_settings['bindir'], filename, daemon_args))
swap_client.setDaemonPID(c, daemons[-1].handle.pid) swap_client.setDaemonPID(c, daemons[-1].pid)
swap_client.setCoinRunParams(c) swap_client.setCoinRunParams(c)
swap_client.createCoinInterface(c) swap_client.createCoinInterface(c)
swap_client.waitForDaemonRPC(c, with_wallet=True) swap_client.waitForDaemonRPC(c, with_wallet=True)
@@ -1273,8 +1183,6 @@ def initialise_wallets(particl_wallet_mnemonic, with_coins, data_dir, settings,
daemons = [] daemons = []
daemon_args = ['-noconnect', '-nodnsseed'] daemon_args = ['-noconnect', '-nodnsseed']
coins_failed_to_initialise = []
with open(os.path.join(data_dir, 'basicswap.log'), 'a') as fp: with open(os.path.join(data_dir, 'basicswap.log'), 'a') as fp:
try: try:
swap_client = BasicSwap(fp, data_dir, settings, chain, transient_instance=True) swap_client = BasicSwap(fp, data_dir, settings, chain, transient_instance=True)
@@ -1293,8 +1201,6 @@ def initialise_wallets(particl_wallet_mnemonic, with_coins, data_dir, settings,
if coin_settings['manage_wallet_daemon']: if coin_settings['manage_wallet_daemon']:
filename = 'monero-wallet-rpc' + ('.exe' if os.name == 'nt' else '') filename = 'monero-wallet-rpc' + ('.exe' if os.name == 'nt' else '')
daemons.append(startXmrWalletDaemon(coin_settings['datadir'], coin_settings['bindir'], filename)) daemons.append(startXmrWalletDaemon(coin_settings['datadir'], coin_settings['bindir'], filename))
elif c == Coins.DCR:
pass
else: else:
if coin_settings['manage_daemon']: if coin_settings['manage_daemon']:
filename = coin_name + 'd' + ('.exe' if os.name == 'nt' else '') filename = coin_name + 'd' + ('.exe' if os.name == 'nt' else '')
@@ -1304,23 +1210,10 @@ def initialise_wallets(particl_wallet_mnemonic, with_coins, data_dir, settings,
coin_args += ['-hdseed={}'.format(swap_client.getWalletKey(Coins.FIRO, 1).hex())] coin_args += ['-hdseed={}'.format(swap_client.getWalletKey(Coins.FIRO, 1).hex())]
daemons.append(startDaemon(coin_settings['datadir'], coin_settings['bindir'], filename, daemon_args + coin_args)) daemons.append(startDaemon(coin_settings['datadir'], coin_settings['bindir'], filename, daemon_args + coin_args))
swap_client.setDaemonPID(c, daemons[-1].handle.pid) swap_client.setDaemonPID(c, daemons[-1].pid)
swap_client.setCoinRunParams(c) swap_client.setCoinRunParams(c)
swap_client.createCoinInterface(c) swap_client.createCoinInterface(c)
if c == Coins.DCR:
if coin_settings['manage_wallet_daemon']:
from basicswap.interface.dcr.util import createDCRWallet
dcr_password = coin_settings['wallet_pwd'] if WALLET_ENCRYPTION_PWD == '' else WALLET_ENCRYPTION_PWD
extra_opts = ['--appdata="{}"'.format(coin_settings['datadir']),
'--pass={}'.format(dcr_password),
]
filename = 'dcrwallet' + ('.exe' if os.name == 'nt' else '')
args = [os.path.join(coin_settings['bindir'], filename), '--create'] + extra_opts
hex_seed = swap_client.getWalletKey(Coins.DCR, 1).hex()
createDCRWallet(args, hex_seed, logger, threading.Event())
if c in coins_to_create_wallets_for: if c in coins_to_create_wallets_for:
swap_client.waitForDaemonRPC(c, with_wallet=False) swap_client.waitForDaemonRPC(c, with_wallet=False)
# Create wallet if it doesn't exist yet # Create wallet if it doesn't exist yet
@@ -1355,13 +1248,8 @@ def initialise_wallets(particl_wallet_mnemonic, with_coins, data_dir, settings,
c = swap_client.getCoinIdFromName(coin_name) c = swap_client.getCoinIdFromName(coin_name)
if c in (Coins.PART, ): if c in (Coins.PART, ):
continue continue
if c not in (Coins.DCR, ):
# initialiseWallet only sets main_wallet_seedid_
swap_client.waitForDaemonRPC(c) swap_client.waitForDaemonRPC(c)
try: swap_client.initialiseWallet(c)
swap_client.initialiseWallet(c, raise_errors=True)
except Exception as e:
coins_failed_to_initialise.append((c, e))
if WALLET_ENCRYPTION_PWD != '' and c not in coins_to_create_wallets_for: if WALLET_ENCRYPTION_PWD != '' and c not in coins_to_create_wallets_for:
try: try:
swap_client.ci(c).changeWalletPassword('', WALLET_ENCRYPTION_PWD) swap_client.ci(c).changeWalletPassword('', WALLET_ENCRYPTION_PWD)
@@ -1375,17 +1263,6 @@ def initialise_wallets(particl_wallet_mnemonic, with_coins, data_dir, settings,
for d in daemons: for d in daemons:
finalise_daemon(d) finalise_daemon(d)
print('')
for pair in coins_failed_to_initialise:
c, e = pair
if c in (Coins.PIVX, ):
print(f'NOTE - Unable to initialise wallet for {getCoinName(c)}. To complete setup click \'Reseed Wallet\' from the ui page once chain is synced.')
else:
print(f'WARNING - Failed to initialise wallet for {getCoinName(c)}: {e}')
if 'decred' in with_coins and WALLET_ENCRYPTION_PWD != '':
print('WARNING - dcrwallet requires the password to be entered at the first startup when encrypted.\nPlease use basicswap-run with --startonlycoin=decred and the WALLET_ENCRYPTION_PWD environment var set for the initial sync.')
if particl_wallet_mnemonic is not None: if particl_wallet_mnemonic is not None:
if particl_wallet_mnemonic: if particl_wallet_mnemonic:
# Print directly to stdout for tests # Print directly to stdout for tests
@@ -1666,19 +1543,7 @@ def main():
'override_feerate': 0.002, 'override_feerate': 0.002,
'conf_target': 2, 'conf_target': 2,
'core_version_group': 21, 'core_version_group': 21,
}, 'chain_lookups': 'local',
'bitcoin': {
'connection_type': 'rpc' if 'bitcoin' in with_coins else 'none',
'manage_daemon': True if ('bitcoin' in with_coins and BTC_RPC_HOST == '127.0.0.1') else False,
'rpchost': BTC_RPC_HOST,
'rpcport': BTC_RPC_PORT + port_offset,
'onionport': BTC_ONION_PORT + port_offset,
'datadir': os.getenv('BTC_DATA_DIR', os.path.join(data_dir, 'bitcoin')),
'bindir': os.path.join(bin_dir, 'bitcoin'),
'use_segwit': True,
'blocks_confirmed': 1,
'conf_target': 2,
'core_version_group': 22,
}, },
'litecoin': { 'litecoin': {
'connection_type': 'rpc' if 'litecoin' in with_coins else 'none', 'connection_type': 'rpc' if 'litecoin' in with_coins else 'none',
@@ -1693,26 +1558,21 @@ def main():
'conf_target': 2, 'conf_target': 2,
'core_version_group': 21, 'core_version_group': 21,
'min_relay_fee': 0.00001, 'min_relay_fee': 0.00001,
'chain_lookups': 'local',
}, },
'decred': { 'bitcoin': {
'connection_type': 'rpc' if 'decred' in with_coins else 'none', 'connection_type': 'rpc' if 'bitcoin' in with_coins else 'none',
'manage_daemon': True if ('decred' in with_coins and DCR_RPC_HOST == '127.0.0.1') else False, 'manage_daemon': True if ('bitcoin' in with_coins and BTC_RPC_HOST == '127.0.0.1') else False,
'manage_wallet_daemon': True if ('decred' in with_coins and DCR_WALLET_RPC_HOST == '127.0.0.1') else False, 'rpchost': BTC_RPC_HOST,
'wallet_pwd': DCR_WALLET_PWD if WALLET_ENCRYPTION_PWD == '' else '', 'rpcport': BTC_RPC_PORT + port_offset,
'rpchost': DCR_RPC_HOST, 'onionport': BTC_ONION_PORT + port_offset,
'rpcport': DCR_RPC_PORT + port_offset, 'datadir': os.getenv('BTC_DATA_DIR', os.path.join(data_dir, 'bitcoin')),
'walletrpchost': DCR_WALLET_RPC_HOST, 'bindir': os.path.join(bin_dir, 'bitcoin'),
'walletrpcport': DCR_WALLET_RPC_PORT + port_offset,
'rpcuser': DCR_RPC_USER,
'rpcpassword': DCR_RPC_PWD,
'datadir': os.getenv('DCR_DATA_DIR', os.path.join(data_dir, 'decred')),
'bindir': os.path.join(bin_dir, 'decred'),
'use_csv': True,
'use_segwit': True, 'use_segwit': True,
'blocks_confirmed': 2, 'blocks_confirmed': 1,
'conf_target': 2, 'conf_target': 2,
'core_type_group': 'dcr', 'core_version_group': 22,
'min_relay_fee': 0.00001, 'chain_lookups': 'local',
}, },
'namecoin': { 'namecoin': {
'connection_type': 'rpc' if 'namecoin' in with_coins else 'none', 'connection_type': 'rpc' if 'namecoin' in with_coins else 'none',
@@ -1748,7 +1608,6 @@ def main():
'rpctimeout': 60, 'rpctimeout': 60,
'walletrpctimeout': 120, 'walletrpctimeout': 120,
'walletrpctimeoutlong': 600, 'walletrpctimeoutlong': 600,
'core_type_group': 'xmr',
}, },
'pivx': { 'pivx': {
'connection_type': 'rpc' if 'pivx' in with_coins else 'none', 'connection_type': 'rpc' if 'pivx' in with_coins else 'none',
@@ -1763,6 +1622,7 @@ def main():
'blocks_confirmed': 1, 'blocks_confirmed': 1,
'conf_target': 2, 'conf_target': 2,
'core_version_group': 17, 'core_version_group': 17,
'chain_lookups': 'local',
}, },
'dash': { 'dash': {
'connection_type': 'rpc' if 'dash' in with_coins else 'none', 'connection_type': 'rpc' if 'dash' in with_coins else 'none',
@@ -1777,6 +1637,7 @@ def main():
'blocks_confirmed': 1, 'blocks_confirmed': 1,
'conf_target': 2, 'conf_target': 2,
'core_version_group': 18, 'core_version_group': 18,
'chain_lookups': 'local',
}, },
'firo': { 'firo': {
'connection_type': 'rpc' if 'firo' in with_coins else 'none', 'connection_type': 'rpc' if 'firo' in with_coins else 'none',
@@ -1792,6 +1653,7 @@ def main():
'conf_target': 2, 'conf_target': 2,
'core_version_group': 14, 'core_version_group': 14,
'min_relay_fee': 0.00001, 'min_relay_fee': 0.00001,
'chain_lookups': 'local',
}, },
'navcoin': { 'navcoin': {
'connection_type': 'rpc' if 'navcoin' in with_coins else 'none', 'connection_type': 'rpc' if 'navcoin' in with_coins else 'none',

View File

@@ -18,7 +18,6 @@ import basicswap.config as cfg
from basicswap import __version__ from basicswap import __version__
from basicswap.ui.util import getCoinName from basicswap.ui.util import getCoinName
from basicswap.basicswap import BasicSwap from basicswap.basicswap import BasicSwap
from basicswap.chainparams import chainparams
from basicswap.http_server import HttpThread from basicswap.http_server import HttpThread
from basicswap.contrib.websocket_server import WebsocketServer from basicswap.contrib.websocket_server import WebsocketServer
@@ -29,21 +28,18 @@ if not len(logger.handlers):
logger.addHandler(logging.StreamHandler(sys.stdout)) logger.addHandler(logging.StreamHandler(sys.stdout))
swap_client = None swap_client = None
# TODO: deduplicate
known_coins = [
class Daemon: 'particl',
__slots__ = ('handle', 'files') 'litecoin',
'bitcoin',
def __init__(self, handle, files): 'namecoin',
self.handle = handle 'monero',
self.files = files 'pivx',
'dash',
'firo',
def is_known_coin(coin_name: str) -> bool: 'navcoin',
for k, v in chainparams.items(): ]
if coin_name == v['name']:
return True
return False
def signal_handler(sig, frame): def signal_handler(sig, frame):
@@ -53,45 +49,13 @@ def signal_handler(sig, frame):
swap_client.stopRunning() swap_client.stopRunning()
def startDaemon(node_dir, bin_dir, daemon_bin, opts=[], extra_config={}): def startDaemon(node_dir, bin_dir, daemon_bin, opts=[]):
daemon_bin = os.path.expanduser(os.path.join(bin_dir, daemon_bin)) daemon_bin = os.path.expanduser(os.path.join(bin_dir, daemon_bin))
datadir_path = os.path.expanduser(node_dir) datadir_path = os.path.expanduser(node_dir)
args = [daemon_bin, '-datadir=' + datadir_path] + opts
# Rewrite litecoin.conf for 0.21.3 logging.info('Starting node ' + daemon_bin + ' ' + '-datadir=' + node_dir)
ltc_conf_path = os.path.join(datadir_path, 'litecoin.conf') return subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=datadir_path)
if os.path.exists(ltc_conf_path):
config_to_add = ['blockfilterindex=0', 'peerblockfilters=0']
with open(ltc_conf_path) as fp:
for line in fp:
line = line.strip()
if line in config_to_add:
config_to_add.remove(line)
if len(config_to_add) > 0:
logging.info('Rewriting litecoin.conf')
shutil.copyfile(ltc_conf_path, ltc_conf_path + '.last')
with open(ltc_conf_path, 'a') as fp:
for line in config_to_add:
fp.write(line + '\n')
args = [daemon_bin, ]
add_datadir: bool = extra_config.get('add_datadir', True)
if add_datadir:
args.append('-datadir=' + datadir_path)
args += opts
logging.info('Starting node ' + daemon_bin + ' ' + (('-datadir=' + node_dir) if add_datadir else ''))
opened_files = []
if extra_config.get('stdout_to_file', False):
stdout_dest = open(os.path.join(datadir_path, extra_config.get('stdout_filename', 'core_stdout.log')), 'w')
opened_files.append(stdout_dest)
stderr_dest = stdout_dest
else:
stdout_dest = subprocess.PIPE
stderr_dest = subprocess.PIPE
return Daemon(subprocess.Popen(args, stdin=subprocess.PIPE, stdout=stdout_dest, stderr=stderr_dest, cwd=datadir_path), opened_files)
def startXmrDaemon(node_dir, bin_dir, daemon_bin, opts=[]): def startXmrDaemon(node_dir, bin_dir, daemon_bin, opts=[]):
@@ -104,41 +68,42 @@ def startXmrDaemon(node_dir, bin_dir, daemon_bin, opts=[]):
# return subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # return subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
file_stdout = open(os.path.join(datadir_path, 'core_stdout.log'), 'w') file_stdout = open(os.path.join(datadir_path, 'core_stdout.log'), 'w')
file_stderr = open(os.path.join(datadir_path, 'core_stderr.log'), 'w') file_stderr = open(os.path.join(datadir_path, 'core_stderr.log'), 'w')
return Daemon(subprocess.Popen(args, stdin=subprocess.PIPE, stdout=file_stdout, stderr=file_stderr, cwd=datadir_path), [file_stdout, file_stderr]) return subprocess.Popen(args, stdin=subprocess.PIPE, stdout=file_stdout, stderr=file_stderr, cwd=datadir_path)
def startXmrWalletDaemon(node_dir, bin_dir, wallet_bin, opts=[]): def startXmrWalletDaemon(node_dir, bin_dir, wallet_bin, opts=[]):
daemon_bin = os.path.expanduser(os.path.join(bin_dir, wallet_bin)) daemon_bin = os.path.expanduser(os.path.join(bin_dir, wallet_bin))
args = [daemon_bin, '--non-interactive']
needs_rewrite: bool = False
config_to_remove = ['daemon-address=', 'untrusted-daemon=', 'trusted-daemon=', 'proxy=']
data_dir = os.path.expanduser(node_dir) data_dir = os.path.expanduser(node_dir)
config_path = os.path.join(data_dir, 'monero_wallet.conf') config_path = os.path.join(data_dir, 'monero_wallet.conf')
if os.path.exists(config_path): args = [daemon_bin, '--non-interactive', '--config-file=' + config_path] + opts
args += ['--config-file=' + config_path]
# TODO: Remove
# Remove daemon-address
has_daemon_address = False
has_untrusted = False
with open(config_path) as fp: with open(config_path) as fp:
for line in fp: for line in fp:
if any(line.startswith(config_line) for config_line in config_to_remove): if line.startswith('daemon-address'):
logging.warning('Found old config in monero_wallet.conf: {}'.format(line.strip())) has_daemon_address = True
needs_rewrite = True if line.startswith('untrusted-daemon'):
args += opts has_untrusted = True
if has_daemon_address:
if needs_rewrite:
logging.info('Rewriting monero_wallet.conf') logging.info('Rewriting monero_wallet.conf')
shutil.copyfile(config_path, config_path + '.last') shutil.copyfile(config_path, config_path + '.last')
with open(config_path + '.last') as fp_from, open(config_path, 'w') as fp_to: with open(config_path + '.last') as fp_from, open(config_path, 'w') as fp_to:
for line in fp_from: for line in fp_from:
if not any(line.startswith(config_line) for config_line in config_to_remove): if not line.startswith('daemon-address'):
fp_to.write(line) fp_to.write(line)
if not has_untrusted:
fp_to.write('untrusted-daemon=1\n')
logging.info('Starting wallet daemon {} --wallet-dir={}'.format(daemon_bin, node_dir)) logging.info('Starting wallet daemon {} --wallet-dir={}'.format(daemon_bin, node_dir))
# TODO: return subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=data_dir) # TODO: return subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=data_dir)
wallet_stdout = open(os.path.join(data_dir, 'wallet_stdout.log'), 'w') wallet_stdout = open(os.path.join(data_dir, 'wallet_stdout.log'), 'w')
wallet_stderr = open(os.path.join(data_dir, 'wallet_stderr.log'), 'w') wallet_stderr = open(os.path.join(data_dir, 'wallet_stderr.log'), 'w')
return Daemon(subprocess.Popen(args, stdin=subprocess.PIPE, stdout=wallet_stdout, stderr=wallet_stderr, cwd=data_dir), [wallet_stdout, wallet_stderr]) return subprocess.Popen(args, stdin=subprocess.PIPE, stdout=wallet_stdout, stderr=wallet_stderr, cwd=data_dir)
def ws_new_client(client, server): def ws_new_client(client, server):
@@ -169,10 +134,6 @@ def runClient(fp, data_dir, chain, start_only_coins):
pids_path = os.path.join(data_dir, '.pids') pids_path = os.path.join(data_dir, '.pids')
if os.getenv('WALLET_ENCRYPTION_PWD', '') != '': if os.getenv('WALLET_ENCRYPTION_PWD', '') != '':
if 'decred' in start_only_coins:
# Workaround for dcrwallet requiring password for initial startup
logger.warning('Allowing set WALLET_ENCRYPTION_PWD var with --startonlycoin=decred.')
else:
raise ValueError('Please unset the WALLET_ENCRYPTION_PWD environment variable.') raise ValueError('Please unset the WALLET_ENCRYPTION_PWD environment variable.')
if not os.path.exists(settings_path): if not os.path.exists(settings_path):
@@ -192,8 +153,6 @@ def runClient(fp, data_dir, chain, start_only_coins):
# Ensure daemons are stopped # Ensure daemons are stopped
swap_client.stopDaemons() swap_client.stopDaemons()
# Settings may have been modified
settings = swap_client.settings
try: try:
# Try start daemons # Try start daemons
for c, v in settings['chainclients'].items(): for c, v in settings['chainclients'].items():
@@ -211,7 +170,7 @@ def runClient(fp, data_dir, chain, start_only_coins):
swap_client.log.info(f'Starting {display_name} daemon') swap_client.log.info(f'Starting {display_name} daemon')
filename = 'monerod' + ('.exe' if os.name == 'nt' else '') filename = 'monerod' + ('.exe' if os.name == 'nt' else '')
daemons.append(startXmrDaemon(v['datadir'], v['bindir'], filename)) daemons.append(startXmrDaemon(v['datadir'], v['bindir'], filename))
pid = daemons[-1].handle.pid pid = daemons[-1].pid
swap_client.log.info('Started {} {}'.format(filename, pid)) swap_client.log.info('Started {} {}'.format(filename, pid))
if v['manage_wallet_daemon'] is True: if v['manage_wallet_daemon'] is True:
@@ -237,46 +196,16 @@ def runClient(fp, data_dir, chain, start_only_coins):
opts.append('--trusted-daemon' if trusted_daemon else '--untrusted-daemon') opts.append('--trusted-daemon' if trusted_daemon else '--untrusted-daemon')
filename = 'monero-wallet-rpc' + ('.exe' if os.name == 'nt' else '') filename = 'monero-wallet-rpc' + ('.exe' if os.name == 'nt' else '')
daemons.append(startXmrWalletDaemon(v['datadir'], v['bindir'], filename, opts)) daemons.append(startXmrWalletDaemon(v['datadir'], v['bindir'], filename, opts))
pid = daemons[-1].handle.pid pid = daemons[-1].pid
swap_client.log.info('Started {} {}'.format(filename, pid)) swap_client.log.info('Started {} {}'.format(filename, pid))
continue # /monero continue
if c == 'decred':
appdata = v['datadir']
extra_opts = [f'--appdata="{appdata}"', ]
if v['manage_daemon'] is True:
swap_client.log.info(f'Starting {display_name} daemon')
filename = 'dcrd' + ('.exe' if os.name == 'nt' else '')
extra_config = {'add_datadir': False, 'stdout_to_file': True, 'stdout_filename': 'dcrd_stdout.log'}
daemons.append(startDaemon(appdata, v['bindir'], filename, opts=extra_opts, extra_config=extra_config))
pid = daemons[-1].handle.pid
swap_client.log.info('Started {} {}'.format(filename, pid))
if v['manage_wallet_daemon'] is True:
swap_client.log.info(f'Starting {display_name} wallet daemon')
filename = 'dcrwallet' + ('.exe' if os.name == 'nt' else '')
wallet_pwd = v['wallet_pwd']
if wallet_pwd == '':
# Only set when in startonlycoin mode
wallet_pwd = os.getenv('WALLET_ENCRYPTION_PWD', '')
if wallet_pwd != '':
extra_opts.append(f'--pass="{wallet_pwd}"')
extra_config = {'add_datadir': False, 'stdout_to_file': True, 'stdout_filename': 'dcrwallet_stdout.log'}
daemons.append(startDaemon(appdata, v['bindir'], filename, opts=extra_opts, extra_config=extra_config))
pid = daemons[-1].handle.pid
swap_client.log.info('Started {} {}'.format(filename, pid))
continue # /decred
if v['manage_daemon'] is True: if v['manage_daemon'] is True:
swap_client.log.info(f'Starting {display_name} daemon') swap_client.log.info(f'Starting {display_name} daemon')
filename = c + 'd' + ('.exe' if os.name == 'nt' else '') filename = c + 'd' + ('.exe' if os.name == 'nt' else '')
daemons.append(startDaemon(v['datadir'], v['bindir'], filename)) daemons.append(startDaemon(v['datadir'], v['bindir'], filename))
pid = daemons[-1].handle.pid pid = daemons[-1].pid
pids.append((c, pid)) pids.append((c, pid))
swap_client.setDaemonPID(c, pid) swap_client.setDaemonPID(c, pid)
swap_client.log.info('Started {} {}'.format(filename, pid)) swap_client.log.info('Started {} {}'.format(filename, pid))
@@ -336,18 +265,18 @@ def runClient(fp, data_dir, chain, start_only_coins):
closed_pids = [] closed_pids = []
for d in daemons: for d in daemons:
swap_client.log.info('Interrupting {}'.format(d.handle.pid)) swap_client.log.info('Interrupting {}'.format(d.pid))
try: try:
d.handle.send_signal(signal.CTRL_C_EVENT if os.name == 'nt' else signal.SIGINT) d.send_signal(signal.CTRL_C_EVENT if os.name == 'nt' else signal.SIGINT)
except Exception as e: except Exception as e:
swap_client.log.info('Interrupting %d, error %s', d.handle.pid, str(e)) swap_client.log.info('Interrupting %d, error %s', d.pid, str(e))
for d in daemons: for d in daemons:
try: try:
d.handle.wait(timeout=120) d.wait(timeout=120)
for fp in [d.handle.stdout, d.handle.stderr, d.handle.stdin] + d.files: for fp in (d.stdout, d.stderr, d.stdin):
if fp: if fp:
fp.close() fp.close()
closed_pids.append(d.handle.pid) closed_pids.append(d.pid)
except Exception as ex: except Exception as ex:
swap_client.log.error('Error: {}'.format(ex)) swap_client.log.error('Error: {}'.format(ex))
@@ -414,7 +343,7 @@ def main():
continue continue
if name == 'startonlycoin': if name == 'startonlycoin':
for coin in [s.lower() for s in s[1].split(',')]: for coin in [s.lower() for s in s[1].split(',')]:
if is_known_coin(coin) is False: if coin not in known_coins:
raise ValueError(f'Unknown coin: {coin}') raise ValueError(f'Unknown coin: {coin}')
start_only_coins.add(coin) start_only_coins.add(coin)
continue continue

View File

@@ -30,21 +30,12 @@ Without this step you will need to preface each `docker-compose` command with `s
https://docs.docker.com/engine/install/linux-postinstall/ https://docs.docker.com/engine/install/linux-postinstall/
#### Copy the default environment file:
cd basicswap/docker
cp example.env .env
#### (Optional) Set custom coin data path:
Coin-related files, such as blockchain and wallet files, are stored in `/var/data/coinswaps` by default. To use a different location, simply modify the target path in your `.env` file found within the `/docker` sub-folder.
cd basicswap/docker
nano .env
#### Create the images: #### Create the images:
COINDATA_PATH can be set to your preference but must be exported each time you launch Basicswap.<br>
Consider adding COINDATA_PATH to the `.env` file in the docker directory file so it's always set.
export COINDATA_PATH=/var/data/coinswaps
cd basicswap/docker cd basicswap/docker
docker-compose build docker-compose build
@@ -66,19 +57,25 @@ Append `--usebtcfastsync` to the below command to optionally initialise the Bitc
Setup with a local Monero daemon (recommended): Setup with a local Monero daemon (recommended):
docker-compose run --rm swapclient basicswap-prepare --datadir=/coindata --withcoins=monero --htmlhost="0.0.0.0" --wshost="0.0.0.0" --xmrrestoreheight=$CURRENT_XMR_HEIGHT export COINDATA_PATH=/var/data/coinswaps
docker run --rm -t --name swap_prepare -v $COINDATA_PATH:/coindata i_swapclient basicswap-prepare --datadir=/coindata --withcoins=monero --htmlhost="0.0.0.0" --wshost="0.0.0.0" --xmrrestoreheight=$CURRENT_XMR_HEIGHT
To instead use Monero public nodes and not run a local Monero daemon<br>(it can be difficult to find reliable public nodes): To instead use Monero public nodes and not run a local Monero daemon<br>(it can be difficult to find reliable public nodes):
Set XMR_RPC_HOST and BASE_XMR_RPC_PORT to a public XMR node. Set XMR_RPC_HOST and BASE_XMR_RPC_PORT to a public XMR node.
docker-compose run --rm -e XMR_RPC_HOST="node.xmr.to" -e BASE_XMR_RPC_PORT=18081 swapclient basicswap-prepare --datadir=/coindata --withcoins=monero --htmlhost="0.0.0.0" --wshost="0.0.0.0" --xmrrestoreheight=$CURRENT_XMR_HEIGHT export COINDATA_PATH=/var/data/coinswaps
docker run --rm -e XMR_RPC_HOST="node.xmr.to" -e BASE_XMR_RPC_PORT=18081 -t --name swap_prepare -v $COINDATA_PATH:/coindata i_swapclient basicswap-prepare --datadir=/coindata --withcoins=monero --htmlhost="0.0.0.0" --wshost="0.0.0.0" --xmrrestoreheight=$CURRENT_XMR_HEIGHT
**Record the mnemonic from the output of the above command.** **Record the mnemonic from the output of the above command.**
**Mnemonics should be stored encrypted and/or air-gapped.** **Mnemonics should be stored encrypted and/or air-gapped.**
And the output of `echo $CURRENT_XMR_HEIGHT` for use if you need to later restore your wallet. And the output of `echo $CURRENT_XMR_HEIGHT` for use if you need to later restore your wallet.
#### Make COINDATA_PATH permanent (optional):
Edit the `.env` file in the docker directory and uncomment COINDATA_PATH line by deleting the hashtag.
#### Set the timezone (optional): #### Set the timezone (optional):
Edit the `.env` file in the docker directory, set TZ to your local timezone. Edit the `.env` file in the docker directory, set TZ to your local timezone.
@@ -87,6 +84,7 @@ Valid options can be listed with: `timedatectl list-timezones`
#### Start the container: #### Start the container:
export COINDATA_PATH=/var/data/coinswaps
docker-compose up docker-compose up
Open in browser: `http://localhost:12700` Open in browser: `http://localhost:12700`
@@ -96,7 +94,8 @@ Open in browser: `http://localhost:12700`
### Add a coin ### Add a coin
docker-compose stop docker-compose stop
docker-compose run --rm swapclient basicswap-prepare --datadir=/coindata --addcoin=bitcoin --usebtcfastsync export COINDATA_PATH=/var/data/coinswaps
docker run --rm -t --name swap_prepare -v $COINDATA_PATH:/coindata i_swapclient basicswap-prepare --datadir=/coindata --addcoin=bitcoin --usebtcfastsync
You can copy an existing pruned datadir (excluding bitcoin.conf and any wallets) over to `$COINDATA_PATH/bitcoin` You can copy an existing pruned datadir (excluding bitcoin.conf and any wallets) over to `$COINDATA_PATH/bitcoin`
Remove any existing wallets after copying over a pruned chain or the Bitcoin daemon won't start. Remove any existing wallets after copying over a pruned chain or the Bitcoin daemon won't start.
@@ -104,7 +103,8 @@ Remove any existing wallets after copying over a pruned chain or the Bitcoin dae
With Encryption With Encryption
docker-compose run --rm -e WALLET_ENCRYPTION_PWD=passwordhere swapclient basicswap-prepare --datadir=/coindata --addcoin=bitcoin --usebtcfastsync export COINDATA_PATH=/var/data/coinswaps
docker run -e WALLET_ENCRYPTION_PWD=passwordhere --rm -t --name swap_prepare -v $COINDATA_PATH:/coindata i_swapclient basicswap-prepare --datadir=/coindata --addcoin=bitcoin --usebtcfastsync
## Windows ## Windows

View File

@@ -1,19 +1,3 @@
0.13.0
==============
- GUI v3.0
- Bid and offer states change when expired.
- bid amounts are specified directly and not constructed from rate.
- Breaks compatibility with prior versions.
- Added enabled_chart_coins setting for which coins to show on the offers page.
- Blank/unset for active coins.
- All for all known coins.
- Comma separated list of coin tickers to show.
- basicswap-run will rewrite litecoin.conf file to add config required to run Litecoin 0.21.3 in pruned mode.
- On new offers page a blank amount-from is auto-filled from amount-to and rate.
0.12.7 0.12.7
============== ==============
@@ -34,11 +18,6 @@
- `rpctimeout`, `walletrpctimeout` and `walletrpctimeoutlong` in the Monero section of basicswap.json. - `rpctimeout`, `walletrpctimeout` and `walletrpctimeoutlong` in the Monero section of basicswap.json.
- `wallet_update_timeout` in basicswap.json to set how long the wallet ui page waits for an rpc response. - `wallet_update_timeout` in basicswap.json to set how long the wallet ui page waits for an rpc response.
- ui: Renamed unconfirmed balance to pending and include immature balance in pending. - ui: Renamed unconfirmed balance to pending and include immature balance in pending.
- Fixed LTC create utxo.
- ui: Changed 'Subtract Fee' option to 'Sweep All' on XMR wallet page.
- ui: Added An Estimate Fee button on XMR wallet page.
- ui: Added a Force Refresh button on XMR wallet page.
- get_balance (if called) at the end of withdrawCoin is correct, subsequent get_balance calls return old balance for a while.
0.12.6 0.12.6

View File

@@ -12,6 +12,8 @@ Update only the code (prepend sudo to each docker command if necessary):
basicswap]$ git pull basicswap]$ git pull
cd docker cd docker
export COINDATA_PATH=[PATH_TO]
(Probably export COINDATA_PATH=/var/data/coinswaps)
docker-compose build docker-compose build
docker-compose up docker-compose up
@@ -19,6 +21,7 @@ If the dependencies have changed the container must be built with `--no-cache`:
basicswap]$ git pull basicswap]$ git pull
cd docker cd docker
export COINDATA_PATH=[PATH_TO]
docker-compose build --no-cache docker-compose build --no-cache
docker-compose up docker-compose up
@@ -27,7 +30,8 @@ If the dependencies have changed the container must be built with `--no-cache`:
After updating the code and rebuilding the container run: After updating the code and rebuilding the container run:
basicswap/docker]$ docker-compose run --rm swapclient \ basicswap/docker]$ export COINDATA_PATH=[PATH_TO]
$ docker-compose run --rm swapclient \
basicswap-prepare --datadir=/coindata --preparebinonly --withcoins=monero,bitcoin basicswap-prepare --datadir=/coindata --preparebinonly --withcoins=monero,bitcoin

View File

@@ -1,5 +1,5 @@
HTML_PORT=127.0.0.1:12700:12700 HTML_PORT=127.0.0.1:12700:12700
WS_PORT=127.0.0.1:11700:11700 WS_PORT=127.0.0.1:11700:11700
COINDATA_PATH=/var/data/coinswaps #COINDATA_PATH=/var/data/coinswaps
TOR_PROXY_HOST=172.16.238.200 TOR_PROXY_HOST=172.16.238.200
TZ=UTC TZ=UTC

View File

@@ -1,96 +0,0 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
O6GuapL0x1I9SeIk9WX9VRrpZmENhlri
=JrM6
-----END PGP PUBLIC KEY BLOCK-----

View File

@@ -1,78 +1,589 @@
-----BEGIN PGP PUBLIC KEY BLOCK----- -----BEGIN PGP PUBLIC KEY BLOCK-----
Comment: Hostname:
Version: Hockeypuck 2.1.0-166-geb2a11b
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
Ng== Dhy+PcCPH+JWZCfSoA4fHaQGEA3ewsGUBBMBCgAnBQJWaUc0AhsDBQkHhh+ABQsJ
=muu4 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
yyX8veaNitVw6fcdY5QlWd5UnhmFXODeGw0tSCmxujpk9FDDG69U6GbffwhjLiwh
2H/kSTLCXWNkm0CMycRHZ17YnBufl6+9zSsP5P1OAR28/FGblHADq1AxzHm+eDhB
LKiMUage5SFJ37FtUGb+8GM8p8TGARPzZ4OMxkagcWtvNJ0OXFUXiN68LqH4Dwwa
6djo5gka0MFo4WdYX/blw2R0xM7to22OsOP2NcSPKrm92SYyotRjEmjQZr4Swy4Z
wSKyouIc0f8AADg5/wAAODQBEAABAQAAAAAAAAAAAAAAAP/Y/9sAhAAIBgYHBgUI
BwcHCQkICgwUDQwLCwwZEhMPFB0aHx4dGhwcICQuJyAiLCMcHCg3KSwwMTQ0NB8n
OT04MjwuMzQyAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy
MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAEoASgDASIAAhEBAxEB/8QB
ogAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoLEAACAQMDAgQDBQUEBAAAAX0B
AgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygp
KjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImK
kpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj
5OXm5+jp6vHy8/T19vf4+foBAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKCxEA
AgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAV
YnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hp
anN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPE
xcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDy
q4XdEkiHOz19KrsFki2P91uuO1LpH76Nw4JCkAc1PcWhiBeBTs7qe1a1KbfvIuMu
jM5bEiT53GzqCDyasZRFEa8D0xT0Vpj8vC55Y9astCiwFVUepJqVCU/iBtLREEcs
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
tXo=
=lheU
-----END PGP PUBLIC KEY BLOCK----- -----END PGP PUBLIC KEY BLOCK-----

View File

@@ -463,7 +463,6 @@ def main():
print(f'Not bidding on offer {offer_id}, too many failed bids ({failed_sent_bids}).') print(f'Not bidding on offer {offer_id}, too many failed bids ({failed_sent_bids}).')
continue continue
validateamount: bool = False
max_coin_from_balance = bid_template.get('max_coin_from_balance', -1) max_coin_from_balance = bid_template.get('max_coin_from_balance', -1)
if max_coin_from_balance > 0: if max_coin_from_balance > 0:
wallet_from = read_json_api_wallet('wallets/{}'.format(coin_from_data['ticker'])) wallet_from = read_json_api_wallet('wallets/{}'.format(coin_from_data['ticker']))
@@ -473,7 +472,6 @@ def main():
if total_balance_from + bid_amount > max_coin_from_balance: if total_balance_from + bid_amount > max_coin_from_balance:
if can_adjust_amount and max_coin_from_balance - total_balance_from > min_swap_amount: if can_adjust_amount and max_coin_from_balance - total_balance_from > min_swap_amount:
bid_amount = max_coin_from_balance - total_balance_from bid_amount = max_coin_from_balance - total_balance_from
validateamount = True
print(f'Reduced bid amount to {bid_amount}') print(f'Reduced bid amount to {bid_amount}')
else: else:
if args.debug: if args.debug:
@@ -495,9 +493,8 @@ def main():
adjusted_bid_amount = adjusted_swap_amount_to / offer_rate adjusted_bid_amount = adjusted_swap_amount_to / offer_rate
if adjusted_bid_amount > min_swap_amount: if adjusted_bid_amount > min_swap_amount:
bid_amount = adjusted_bid_amount
validateamount = True
print(f'Reduced bid amount to {bid_amount}') print(f'Reduced bid amount to {bid_amount}')
bid_amount = adjusted_bid_amount
swap_amount_to = adjusted_bid_amount * offer_rate swap_amount_to = adjusted_bid_amount * offer_rate
if total_balance_to - swap_amount_to < min_coin_to_balance: if total_balance_to - swap_amount_to < min_coin_to_balance:
@@ -505,8 +502,6 @@ def main():
print(f'Bid amount would exceed minimum coin to wallet total for offer {offer_id}') print(f'Bid amount would exceed minimum coin to wallet total for offer {offer_id}')
continue continue
if validateamount:
bid_amount = read_json_api('validateamount', {'coin': coin_from_data['ticker'], 'amount': bid_amount, 'method': 'rounddown'})
bid_data = { bid_data = {
'offer_id': offer['offer_id'], 'offer_id': offer['offer_id'],
'amount_from': bid_amount} 'amount_from': bid_amount}

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2020-2024 tecnovert # Copyright (c) 2020-2023 tecnovert
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file LICENSE.txt or http://www.opensource.org/licenses/mit-license.php. # file LICENSE.txt or http://www.opensource.org/licenses/mit-license.php.
@@ -35,10 +35,6 @@ LTC_BASE_PORT = 34792
LTC_BASE_RPC_PORT = 35792 LTC_BASE_RPC_PORT = 35792
LTC_BASE_ZMQ_PORT = 36792 LTC_BASE_ZMQ_PORT = 36792
DCR_BASE_PORT = 18555
DCR_BASE_RPC_PORT = 9110
PIVX_BASE_PORT = 34892 PIVX_BASE_PORT = 34892
PIVX_BASE_RPC_PORT = 35892 PIVX_BASE_RPC_PORT = 35892
PIVX_BASE_ZMQ_PORT = 36892 PIVX_BASE_ZMQ_PORT = 36892
@@ -112,19 +108,19 @@ def checkForks(ro):
def stopDaemons(daemons): def stopDaemons(daemons):
for d in daemons: for d in daemons:
logging.info('Interrupting %d', d.handle.pid) logging.info('Interrupting %d', d.pid)
try: try:
d.handle.send_signal(signal.SIGINT) d.send_signal(signal.SIGINT)
except Exception as e: except Exception as e:
logging.info('Interrupting %d, error %s', d.handle.pid, str(e)) logging.info('Interrupting %d, error %s', d.pid, str(e))
for d in daemons: for d in daemons:
try: try:
d.handle.wait(timeout=20) d.wait(timeout=20)
for fp in [d.handle.stdout, d.handle.stderr, d.handle.stdin] + d.files: for fp in (d.stdout, d.stderr, d.stdin):
if fp: if fp:
fp.close() fp.close()
except Exception as e: except Exception as e:
logging.info('Closing %d, error %s', d.handle.pid, str(e)) logging.info('Closing %d, error %s', d.pid, str(e))
def wait_for_bid(delay_event, swap_client, bid_id, state=None, sent: bool = False, wait_for: int = 20) -> None: def wait_for_bid(delay_event, swap_client, bid_id, state=None, sent: bool = False, wait_for: int = 20) -> None:
@@ -316,20 +312,6 @@ def make_rpc_func(node_id, base_rpc_port=BASE_RPC_PORT):
return rpc_func return rpc_func
def waitForRPC(rpc_func, delay_event, rpc_command='getwalletinfo', max_tries=7):
for i in range(max_tries + 1):
if delay_event.is_set():
raise ValueError('Test stopped.')
try:
rpc_func(rpc_command)
return
except Exception as ex:
if i < max_tries:
logging.warning('Can\'t connect to RPC: %s. Retrying in %d second/s.', str(ex), (i + 1))
delay_event.wait(i + 1)
raise ValueError('waitForRPC failed')
def extract_states_from_xu_file(file_path, prefix): def extract_states_from_xu_file(file_path, prefix):
states = {} states = {}
@@ -393,7 +375,7 @@ def extract_states_from_xu_file(file_path, prefix):
return states return states
def compare_bid_states(states, expect_states, exact_match: bool = True) -> bool: def compare_bid_states(states, expect_states, exact_match=True):
for i in range(len(states) - 1, -1, -1): for i in range(len(states) - 1, -1, -1):
if states[i][1] == 'Bid Delaying': if states[i][1] == 'Bid Delaying':
@@ -421,20 +403,3 @@ def compare_bid_states(states, expect_states, exact_match: bool = True) -> bool:
logging.info('Have states: {}'.format(json.dumps(states, indent=4))) logging.info('Have states: {}'.format(json.dumps(states, indent=4)))
raise e raise e
return True return True
def compare_bid_states_unordered(states, expect_states, ignore_states=[]) -> bool:
ignore_states.append('Bid Delaying')
for i in range(len(states) - 1, -1, -1):
if states[i][1] in ignore_states:
del states[i]
try:
assert len(states) == len(expect_states)
for state in expect_states:
assert (any(state in s[1] for s in states))
except Exception as e:
logging.info('Expecting states: {}'.format(json.dumps(expect_states, indent=4)))
logging.info('Have states: {}'.format(json.dumps(states, indent=4)))
raise e
return True

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2020-2024 tecnovert # Copyright (c) 2020-2022 tecnovert
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php. # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@@ -29,7 +29,6 @@ from tests.basicswap.common import (
BASE_PORT, BASE_RPC_PORT, BASE_PORT, BASE_RPC_PORT,
BTC_BASE_PORT, BTC_BASE_RPC_PORT, BTC_BASE_TOR_PORT, BTC_BASE_PORT, BTC_BASE_RPC_PORT, BTC_BASE_TOR_PORT,
LTC_BASE_PORT, LTC_BASE_RPC_PORT, LTC_BASE_PORT, LTC_BASE_RPC_PORT,
DCR_BASE_PORT, DCR_BASE_RPC_PORT,
PIVX_BASE_PORT, PIVX_BASE_PORT,
) )
from basicswap.contrib.rpcauth import generate_salt, password_to_hmac from basicswap.contrib.rpcauth import generate_salt, password_to_hmac
@@ -47,7 +46,6 @@ BITCOIN_RPC_PORT_BASE = int(os.getenv('BITCOIN_RPC_PORT_BASE', BTC_BASE_RPC_PORT
BITCOIN_TOR_PORT_BASE = int(os.getenv('BITCOIN_TOR_PORT_BASE', BTC_BASE_TOR_PORT)) BITCOIN_TOR_PORT_BASE = int(os.getenv('BITCOIN_TOR_PORT_BASE', BTC_BASE_TOR_PORT))
LITECOIN_RPC_PORT_BASE = int(os.getenv('LITECOIN_RPC_PORT_BASE', LTC_BASE_RPC_PORT)) LITECOIN_RPC_PORT_BASE = int(os.getenv('LITECOIN_RPC_PORT_BASE', LTC_BASE_RPC_PORT))
DECRED_RPC_PORT_BASE = int(os.getenv('DECRED_RPC_PORT_BASE', DCR_BASE_RPC_PORT))
FIRO_BASE_PORT = 34832 FIRO_BASE_PORT = 34832
FIRO_BASE_RPC_PORT = 35832 FIRO_BASE_RPC_PORT = 35832
@@ -95,14 +93,11 @@ def run_prepare(node_id, datadir_path, bins_path, with_coins, mnemonic_in=None,
os.environ['PART_RPC_PORT'] = str(PARTICL_RPC_PORT_BASE) os.environ['PART_RPC_PORT'] = str(PARTICL_RPC_PORT_BASE)
os.environ['BTC_RPC_PORT'] = str(BITCOIN_RPC_PORT_BASE) os.environ['BTC_RPC_PORT'] = str(BITCOIN_RPC_PORT_BASE)
os.environ['LTC_RPC_PORT'] = str(LITECOIN_RPC_PORT_BASE) os.environ['LTC_RPC_PORT'] = str(LITECOIN_RPC_PORT_BASE)
os.environ['DCR_RPC_PORT'] = str(DECRED_RPC_PORT_BASE)
os.environ['FIRO_RPC_PORT'] = str(FIRO_RPC_PORT_BASE) os.environ['FIRO_RPC_PORT'] = str(FIRO_RPC_PORT_BASE)
os.environ['XMR_RPC_USER'] = 'xmr_user' os.environ['XMR_RPC_USER'] = 'xmr_user'
os.environ['XMR_RPC_PWD'] = 'xmr_pwd' os.environ['XMR_RPC_PWD'] = 'xmr_pwd'
os.environ['DCR_RPC_PWD'] = 'dcr_pwd'
import bin.basicswap_prepare as prepareSystem import bin.basicswap_prepare as prepareSystem
# Hack: Reload module to set env vars as the basicswap_prepare module is initialised if imported from elsewhere earlier # Hack: Reload module to set env vars as the basicswap_prepare module is initialised if imported from elsewhere earlier
from importlib import reload from importlib import reload
@@ -131,10 +126,9 @@ def run_prepare(node_id, datadir_path, bins_path, with_coins, mnemonic_in=None,
with open(config_path) as fs: with open(config_path) as fs:
settings = json.load(fs) settings = json.load(fs)
config_filename = os.path.join(datadir_path, 'particl', 'particl.conf') with open(os.path.join(datadir_path, 'particl', 'particl.conf'), 'r') as fp:
with open(config_filename, 'r') as fp:
lines = fp.readlines() lines = fp.readlines()
with open(config_filename, 'w') as fp: with open(os.path.join(datadir_path, 'particl', 'particl.conf'), 'w') as fp:
for line in lines: for line in lines:
if not line.startswith('staking'): if not line.startswith('staking'):
fp.write(line) fp.write(line)
@@ -164,10 +158,9 @@ def run_prepare(node_id, datadir_path, bins_path, with_coins, mnemonic_in=None,
if 'bitcoin' in coins_array: if 'bitcoin' in coins_array:
# Pruned nodes don't provide blocks # Pruned nodes don't provide blocks
config_filename = os.path.join(datadir_path, 'bitcoin', 'bitcoin.conf') with open(os.path.join(datadir_path, 'bitcoin', 'bitcoin.conf'), 'r') as fp:
with open(config_filename, 'r') as fp:
lines = fp.readlines() lines = fp.readlines()
with open(config_filename, 'w') as fp: with open(os.path.join(datadir_path, 'bitcoin', 'bitcoin.conf'), 'w') as fp:
for line in lines: for line in lines:
if not line.startswith('prune'): if not line.startswith('prune'):
fp.write(line) fp.write(line)
@@ -195,10 +188,9 @@ def run_prepare(node_id, datadir_path, bins_path, with_coins, mnemonic_in=None,
if 'litecoin' in coins_array: if 'litecoin' in coins_array:
# Pruned nodes don't provide blocks # Pruned nodes don't provide blocks
config_filename = os.path.join(datadir_path, 'litecoin', 'litecoin.conf') with open(os.path.join(datadir_path, 'litecoin', 'litecoin.conf'), 'r') as fp:
with open(config_filename, 'r') as fp:
lines = fp.readlines() lines = fp.readlines()
with open(config_filename, 'w') as fp: with open(os.path.join(datadir_path, 'litecoin', 'litecoin.conf'), 'w') as fp:
for line in lines: for line in lines:
if not line.startswith('prune'): if not line.startswith('prune'):
fp.write(line) fp.write(line)
@@ -221,34 +213,11 @@ def run_prepare(node_id, datadir_path, bins_path, with_coins, mnemonic_in=None,
for opt in EXTRA_CONFIG_JSON.get('ltc{}'.format(node_id), []): for opt in EXTRA_CONFIG_JSON.get('ltc{}'.format(node_id), []):
fp.write(opt + '\n') fp.write(opt + '\n')
if 'decred' in coins_array:
# Pruned nodes don't provide blocks
config_filename = os.path.join(datadir_path, 'decred', 'dcrd.conf')
with open(config_filename, 'r') as fp:
lines = fp.readlines()
with open(config_filename, 'w') as fp:
for line in lines:
if not line.startswith('prune'):
fp.write(line)
fp.write('listen=127.0.0.1:{}\n'.format(DCR_BASE_PORT + node_id + port_ofs))
fp.write('noseeders=1\n')
fp.write('nodnsseed=1\n')
fp.write('nodiscoverip=1\n')
if node_id == 0:
fp.write('miningaddr=SsYbXyjkKAEXXcGdFgr4u4bo4L8RkCxwQpH\n')
for ip in range(num_nodes):
if ip != node_id:
fp.write('addpeer=127.0.0.1:{}\n'.format(DCR_BASE_PORT + ip + port_ofs))
config_filename = os.path.join(datadir_path, 'decred', 'dcrwallet.conf')
with open(config_filename, 'a') as fp:
fp.write('enablevoting=1\n')
if 'pivx' in coins_array: if 'pivx' in coins_array:
# Pruned nodes don't provide blocks # Pruned nodes don't provide blocks
config_filename = os.path.join(datadir_path, 'pivx', 'pivx.conf') with open(os.path.join(datadir_path, 'pivx', 'pivx.conf'), 'r') as fp:
with open(config_filename, 'r') as fp:
lines = fp.readlines() lines = fp.readlines()
with open(config_filename, 'w') as fp: with open(os.path.join(datadir_path, 'pivx', 'pivx.conf'), 'w') as fp:
for line in lines: for line in lines:
if not line.startswith('prune'): if not line.startswith('prune'):
fp.write(line) fp.write(line)
@@ -273,10 +242,9 @@ def run_prepare(node_id, datadir_path, bins_path, with_coins, mnemonic_in=None,
if 'firo' in coins_array: if 'firo' in coins_array:
# Pruned nodes don't provide blocks # Pruned nodes don't provide blocks
config_filename = os.path.join(datadir_path, 'firo', 'firo.conf') with open(os.path.join(datadir_path, 'firo', 'firo.conf'), 'r') as fp:
with open(config_filename, 'r') as fp:
lines = fp.readlines() lines = fp.readlines()
with open(config_filename, 'w') as fp: with open(os.path.join(datadir_path, 'firo', 'firo.conf'), 'w') as fp:
for line in lines: for line in lines:
if not line.startswith('prune'): if not line.startswith('prune'):
fp.write(line) fp.write(line)

Some files were not shown because too many files have changed in this diff Show More