mirror of
https://github.com/basicswap/basicswap.git
synced 2026-03-01 08:55:10 +01:00
Compare commits
1 Commits
decred
...
mweb_uncon
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a6e7d36e84 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -12,4 +12,3 @@ __pycache__
|
||||
|
||||
# geckodriver.log
|
||||
*.log
|
||||
docker/.env
|
||||
|
||||
@@ -100,7 +100,7 @@ If you’d like to add a cryptocurrency to BasicSwap, either [apply for a listin
|
||||
|
||||
### 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) [](https://discord.me/particl).
|
||||
|
||||
[](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)
|
||||
|
||||
* [Matrix](https://matrix.to/#/#particlhelp:matrix.org)
|
||||
* [Element](https://app.element.io/#/room/#particlhelp:matrix.org)
|
||||
|
||||
# Tutorials
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
name = "basicswap"
|
||||
|
||||
__version__ = "0.13.1"
|
||||
__version__ = "0.12.7"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2021-2024 tecnovert
|
||||
# Copyright (c) 2021-2023 tecnovert
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
@@ -70,7 +70,6 @@ class OfferStates(IntEnum):
|
||||
OFFER_SENT = 1
|
||||
OFFER_RECEIVED = 2
|
||||
OFFER_ABANDONED = 3
|
||||
OFFER_EXPIRED = 4
|
||||
|
||||
|
||||
class BidStates(IntEnum):
|
||||
@@ -104,7 +103,6 @@ class BidStates(IntEnum):
|
||||
XMR_SWAP_MSG_SCRIPT_LOCK_SPEND_TX = 28 # XmrBidLockSpendTxMessage
|
||||
BID_REQUEST_SENT = 29
|
||||
BID_REQUEST_ACCEPTED = 30
|
||||
BID_EXPIRED = 31
|
||||
|
||||
|
||||
class TxStates(IntEnum):
|
||||
@@ -202,8 +200,6 @@ class DebugTypes(IntEnum):
|
||||
SEND_LOCKED_XMR = auto()
|
||||
B_LOCK_TX_MISSED_SEND = auto()
|
||||
DUPLICATE_ACTIONS = auto()
|
||||
DONT_CONFIRM_PTX = auto()
|
||||
OFFER_LOCK_2_VALUE_INC = auto()
|
||||
|
||||
|
||||
class NotificationTypes(IntEnum):
|
||||
@@ -252,8 +248,6 @@ def strOfferState(state):
|
||||
return 'Received'
|
||||
if state == OfferStates.OFFER_ABANDONED:
|
||||
return 'Abandoned'
|
||||
if state == OfferStates.OFFER_EXPIRED:
|
||||
return 'Expired'
|
||||
return 'Unknown'
|
||||
|
||||
|
||||
@@ -318,8 +312,7 @@ def strBidState(state):
|
||||
return 'Request accepted'
|
||||
if state == BidStates.BID_STATE_UNKNOWN:
|
||||
return 'Unknown bid state'
|
||||
if state == BidStates.BID_EXPIRED:
|
||||
return 'Expired'
|
||||
|
||||
return 'Unknown' + ' ' + str(state)
|
||||
|
||||
|
||||
@@ -510,7 +503,7 @@ def strSwapDesc(swap_type):
|
||||
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):
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2019-2024 tecnovert
|
||||
# Copyright (c) 2019-2023 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 .util import (
|
||||
COIN,
|
||||
make_int,
|
||||
format_amount,
|
||||
TemporaryError,
|
||||
)
|
||||
|
||||
XMR_COIN = 10 ** 12
|
||||
@@ -16,7 +21,7 @@ class Coins(IntEnum):
|
||||
PART = 1
|
||||
BTC = 2
|
||||
LTC = 3
|
||||
DCR = 4
|
||||
# DCR = 4
|
||||
NMC = 5
|
||||
XMR = 6
|
||||
PART_BLIND = 7
|
||||
@@ -150,41 +155,6 @@ chainparams = {
|
||||
'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: {
|
||||
'name': 'namecoin',
|
||||
'ticker': 'NMC',
|
||||
@@ -230,21 +200,18 @@ chainparams = {
|
||||
'walletrpcport': 18082,
|
||||
'min_amount': 100000,
|
||||
'max_amount': 10000 * XMR_COIN,
|
||||
'address_prefix': 18,
|
||||
},
|
||||
'testnet': {
|
||||
'rpcport': 28081,
|
||||
'walletrpcport': 28082,
|
||||
'min_amount': 100000,
|
||||
'max_amount': 10000 * XMR_COIN,
|
||||
'address_prefix': 18,
|
||||
},
|
||||
'regtest': {
|
||||
'rpcport': 18081,
|
||||
'walletrpcport': 18082,
|
||||
'min_amount': 100000,
|
||||
'max_amount': 10000 * XMR_COIN,
|
||||
'address_prefix': 18,
|
||||
}
|
||||
},
|
||||
Coins.PIVX: {
|
||||
@@ -417,3 +384,89 @@ def getCoinIdFromTicker(ticker):
|
||||
return ticker_map[ticker.lower()]
|
||||
except Exception:
|
||||
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
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
|
||||
@@ -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)
|
||||
@@ -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')
|
||||
@@ -1,17 +1,18 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2019-2024 tecnovert
|
||||
# Copyright (c) 2019-2023 tecnovert
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
import time
|
||||
import struct
|
||||
import sqlalchemy as sa
|
||||
|
||||
from enum import IntEnum, auto
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
|
||||
|
||||
CURRENT_DB_VERSION = 24
|
||||
CURRENT_DB_VERSION = 22
|
||||
CURRENT_DB_DATA_VERSION = 4
|
||||
Base = declarative_base()
|
||||
|
||||
@@ -33,10 +34,6 @@ def strConcepts(state):
|
||||
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):
|
||||
__tablename__ = 'kv_int'
|
||||
|
||||
@@ -61,7 +58,6 @@ class Offer(Base):
|
||||
coin_from = sa.Column(sa.Integer)
|
||||
coin_to = sa.Column(sa.Integer)
|
||||
amount_from = sa.Column(sa.BigInteger)
|
||||
amount_to = sa.Column(sa.BigInteger)
|
||||
rate = sa.Column(sa.BigInteger)
|
||||
min_bid_amount = sa.Column(sa.BigInteger)
|
||||
time_valid = sa.Column(sa.BigInteger)
|
||||
@@ -100,9 +96,9 @@ class Offer(Base):
|
||||
now = int(time.time())
|
||||
self.state = new_state
|
||||
if self.states is None:
|
||||
self.states = pack_state(new_state, now)
|
||||
self.states = struct.pack('<iq', new_state, now)
|
||||
else:
|
||||
self.states += pack_state(new_state, now)
|
||||
self.states += struct.pack('<iq', new_state, now)
|
||||
|
||||
|
||||
class Bid(Base):
|
||||
@@ -127,7 +123,6 @@ class Bid(Base):
|
||||
amount_to = sa.Column(sa.BigInteger) # amount * offer.rate
|
||||
|
||||
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)
|
||||
rate = sa.Column(sa.BigInteger)
|
||||
|
||||
@@ -188,14 +183,9 @@ class Bid(Base):
|
||||
if state_note is not None:
|
||||
self.state_note = state_note
|
||||
if self.states is None:
|
||||
self.states = pack_state(new_state, now)
|
||||
self.states = struct.pack('<iq', new_state, now)
|
||||
else:
|
||||
self.states += pack_state(new_state, now)
|
||||
|
||||
def getLockTXBVout(self):
|
||||
if self.xmr_b_lock_tx:
|
||||
return self.xmr_b_lock_tx.vout
|
||||
return None
|
||||
self.states += struct.pack('<iq', new_state, now)
|
||||
|
||||
|
||||
class SwapTx(Base):
|
||||
@@ -232,11 +222,7 @@ class SwapTx(Base):
|
||||
if self.state == new_state:
|
||||
return
|
||||
self.state = new_state
|
||||
now: int = int(time.time())
|
||||
if self.states is None:
|
||||
self.states = pack_state(new_state, now)
|
||||
else:
|
||||
self.states += pack_state(new_state, now)
|
||||
self.states = (self.states if self.states is not None else bytes()) + struct.pack('<iq', new_state, int(time.time()))
|
||||
|
||||
|
||||
class PrefundedTx(Base):
|
||||
@@ -528,14 +514,3 @@ class MessageLink(Base):
|
||||
msg_type = sa.Column(sa.Integer)
|
||||
msg_sequence = sa.Column(sa.Integer)
|
||||
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)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2022-2024 tecnovert
|
||||
# Copyright (c) 2022-2023 tecnovert
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
@@ -297,21 +297,7 @@ def upgradeDatabase(self, db_version):
|
||||
db_version += 1
|
||||
session.execute('ALTER TABLE offers 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:
|
||||
self.db_version = db_version
|
||||
self.setIntKVInSession('db_version', db_version, session)
|
||||
|
||||
@@ -52,7 +52,5 @@ def remove_expired_data(self, time_offset: int = 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 ''))
|
||||
|
||||
session.execute('DELETE FROM checkedblocks WHERE created_at <= :expired_at', {'expired_at': now - time_offset})
|
||||
|
||||
finally:
|
||||
self.closeSession(session)
|
||||
|
||||
@@ -98,8 +98,6 @@ def parse_cmd(cmd: str, type_map: str):
|
||||
type_ind = type_map[i]
|
||||
if type_ind == 'i':
|
||||
typed_params.append(int(param))
|
||||
elif type_ind == 'f':
|
||||
typed_params.append(float(param))
|
||||
elif type_ind == 'b':
|
||||
typed_params.append(toBool(param))
|
||||
elif type_ind == 'j':
|
||||
@@ -267,7 +265,6 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||
summary = swap_client.getSummary()
|
||||
|
||||
result = None
|
||||
cmd = ''
|
||||
coin_type = -1
|
||||
coin_id = -1
|
||||
call_type = 'cli'
|
||||
@@ -285,16 +282,11 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||
coin_type = Coins(Coins.XMR)
|
||||
elif coin_id in (-5,):
|
||||
coin_type = Coins(Coins.LTC)
|
||||
elif coin_id in (-6,):
|
||||
coin_type = Coins(Coins.DCR)
|
||||
else:
|
||||
coin_type = Coins(coin_id)
|
||||
except Exception:
|
||||
raise ValueError('Unknown Coin Type')
|
||||
|
||||
if coin_type in (Coins.DCR,):
|
||||
call_type = 'http'
|
||||
|
||||
try:
|
||||
cmd = get_data_entry(form_data, 'cmd')
|
||||
except Exception:
|
||||
@@ -317,24 +309,18 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||
result = json.dumps(rv, indent=4)
|
||||
else:
|
||||
if call_type == 'http':
|
||||
ci = swap_client.ci(coin_type)
|
||||
method, params = parse_cmd(cmd, type_map)
|
||||
if coin_id == -6:
|
||||
rv = ci.rpc_wallet(method, params)
|
||||
elif coin_id == -5:
|
||||
rv = ci.rpc_wallet_mweb(method, params)
|
||||
if coin_id == -5:
|
||||
rv = swap_client.ci(coin_type).rpc_wallet_mweb(method, params)
|
||||
else:
|
||||
if coin_type in (Coins.DCR, ):
|
||||
rv = ci.rpc(method, params)
|
||||
else:
|
||||
rv = ci.rpc_wallet(method, params)
|
||||
rv = swap_client.ci(coin_type).rpc_wallet(method, params)
|
||||
if not isinstance(rv, str):
|
||||
rv = json.dumps(rv, indent=4)
|
||||
result = cmd + '\n' + rv
|
||||
else:
|
||||
result = cmd + '\n' + swap_client.callcoincli(coin_type, cmd)
|
||||
except Exception as ex:
|
||||
result = cmd + '\n' + str(ex)
|
||||
result = str(ex)
|
||||
if self.server.swap_client.debug is True:
|
||||
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)
|
||||
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):
|
||||
coins.append((-5, 'Litecoin MWEB Wallet'))
|
||||
if with_xmr:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
@@ -5,31 +5,25 @@
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
import json
|
||||
import base64
|
||||
import hashlib
|
||||
import json
|
||||
import logging
|
||||
import traceback
|
||||
|
||||
from io import BytesIO
|
||||
|
||||
from basicswap.basicswap_util import (
|
||||
getVoutByAddress,
|
||||
getVoutByScriptPubKey,
|
||||
)
|
||||
from basicswap.contrib.test_framework import (
|
||||
segwit_addr,
|
||||
)
|
||||
from basicswap.interface.base import (
|
||||
Secp256k1Interface,
|
||||
)
|
||||
from basicswap.contrib.test_framework import segwit_addr
|
||||
|
||||
from basicswap.interface import (
|
||||
Curves)
|
||||
from basicswap.util import (
|
||||
ensure,
|
||||
b2h, i2b, b2i, i2h,
|
||||
)
|
||||
make_int,
|
||||
b2h, i2b, b2i, i2h)
|
||||
from basicswap.util.ecc import (
|
||||
ep,
|
||||
pointToCPK, CPKToPoint,
|
||||
)
|
||||
getSecretInt)
|
||||
from basicswap.util.script import (
|
||||
decodeScriptNum,
|
||||
getCompactSizeLen,
|
||||
@@ -43,20 +37,16 @@ from basicswap.util.address import (
|
||||
decodeAddress,
|
||||
pubkeyToAddress,
|
||||
)
|
||||
from basicswap.util.crypto import (
|
||||
hash160,
|
||||
sha256,
|
||||
)
|
||||
from coincurve.keys import (
|
||||
PrivateKey,
|
||||
PublicKey,
|
||||
)
|
||||
PublicKey)
|
||||
from coincurve.dleag import (
|
||||
verify_secp256k1_point)
|
||||
from coincurve.ecdsaotves import (
|
||||
ecdsaotves_enc_sign,
|
||||
ecdsaotves_enc_verify,
|
||||
ecdsaotves_dec_sig,
|
||||
ecdsaotves_rec_enc_key
|
||||
)
|
||||
ecdsaotves_rec_enc_key)
|
||||
|
||||
from basicswap.contrib.test_framework.messages import (
|
||||
COIN,
|
||||
@@ -65,7 +55,8 @@ from basicswap.contrib.test_framework.messages import (
|
||||
CTxIn,
|
||||
CTxInWitness,
|
||||
CTxOut,
|
||||
)
|
||||
uint256_from_str)
|
||||
|
||||
from basicswap.contrib.test_framework.script import (
|
||||
CScript, CScriptOp,
|
||||
OP_IF, OP_ELSE, OP_ENDIF,
|
||||
@@ -77,12 +68,12 @@ from basicswap.contrib.test_framework.script import (
|
||||
OP_HASH160, OP_EQUAL,
|
||||
SIGHASH_ALL,
|
||||
SegwitV0SignatureHash,
|
||||
)
|
||||
from basicswap.basicswap_util import (
|
||||
TxLockTypes
|
||||
)
|
||||
hash160)
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
def extractScriptLockScriptValues(script_bytes: bytes) -> (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 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):
|
||||
class BTCInterface(CoinInterface):
|
||||
@staticmethod
|
||||
def curve_type():
|
||||
return Curves.secp256k1
|
||||
|
||||
@staticmethod
|
||||
def coin_type():
|
||||
@@ -206,6 +149,10 @@ class BTCInterface(Secp256k1Interface):
|
||||
rv += output.nValue
|
||||
return rv
|
||||
|
||||
@staticmethod
|
||||
def compareFeeRates(a, b) -> bool:
|
||||
return abs(a - b) < 20
|
||||
|
||||
@staticmethod
|
||||
def xmr_swap_a_lock_spend_tx_vsize() -> int:
|
||||
return 147
|
||||
@@ -220,7 +167,7 @@ class BTCInterface(Secp256k1Interface):
|
||||
|
||||
@staticmethod
|
||||
def getExpectedSequence(lockType: int, lockVal: int) -> int:
|
||||
ensure(lockVal >= 1, 'Bad lockVal')
|
||||
assert (lockVal >= 1), 'Bad lockVal'
|
||||
if lockType == TxLockTypes.SEQUENCE_LOCK_BLOCKS:
|
||||
return lockVal
|
||||
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._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:
|
||||
wallets = self.rpc('listwallets')
|
||||
|
||||
@@ -293,6 +223,40 @@ class BTCInterface(Secp256k1Interface):
|
||||
|
||||
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:
|
||||
self.rpc_wallet('getwalletinfo' if with_wallet else 'getblockchaininfo')
|
||||
|
||||
@@ -321,7 +285,7 @@ class BTCInterface(Secp256k1Interface):
|
||||
|
||||
max_tries = 5000
|
||||
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:
|
||||
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'))
|
||||
return rv
|
||||
|
||||
def walletRestoreHeight(self) -> int:
|
||||
return self._restore_height
|
||||
|
||||
def getWalletRestoreHeight(self) -> int:
|
||||
start_time = self.rpc_wallet('getwalletinfo')['keypoololdest']
|
||||
|
||||
@@ -386,6 +353,18 @@ class BTCInterface(Secp256k1Interface):
|
||||
self._log.debug('validateaddress failed: {}'.format(address))
|
||||
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:
|
||||
addr_info = self.rpc_wallet('getaddressinfo', [address])
|
||||
if not or_watch_only:
|
||||
@@ -443,11 +422,11 @@ class BTCInterface(Secp256k1Interface):
|
||||
return segwit_addr.encode(bech32_prefix, version, pkh)
|
||||
|
||||
def pkh_to_address(self, pkh: bytes) -> str:
|
||||
# pkh is ripemd160(sha256(pk))
|
||||
# pkh is hash160(pk)
|
||||
assert (len(pkh) == 20)
|
||||
prefix = self.chainparams_network()['pubkey_address']
|
||||
data = bytes((prefix,)) + pkh
|
||||
checksum = sha256(sha256(data))
|
||||
checksum = hashlib.sha256(hashlib.sha256(data).digest()).digest()
|
||||
return b58encode(data + checksum[0:4])
|
||||
|
||||
def sh_to_address(self, sh: bytes) -> str:
|
||||
@@ -473,6 +452,12 @@ class BTCInterface(Secp256k1Interface):
|
||||
assert (len(pk) == 33)
|
||||
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:
|
||||
pk = self.getPubkey(key)
|
||||
return hash160(pk)
|
||||
@@ -480,6 +465,13 @@ class BTCInterface(Secp256k1Interface):
|
||||
def getSeedHash(self, seed) -> bytes:
|
||||
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:
|
||||
wif_prefix = self.chainparams_network()['key_prefix']
|
||||
return toWIF(wif_prefix, key_bytes)
|
||||
@@ -499,6 +491,13 @@ class BTCInterface(Secp256k1Interface):
|
||||
def decodeKey(self, k: str) -> bytes:
|
||||
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:
|
||||
# p2wpkh
|
||||
return CScript([OP_0, pkh])
|
||||
@@ -509,6 +508,24 @@ class BTCInterface(Secp256k1Interface):
|
||||
tx.deserialize(BytesIO(tx_bytes))
|
||||
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:
|
||||
tx = CTransaction()
|
||||
tx.nVersion = self.txVersion()
|
||||
@@ -518,6 +535,37 @@ class BTCInterface(Secp256k1Interface):
|
||||
def fundSCLockTx(self, tx_bytes, feerate, vkbv=None):
|
||||
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:
|
||||
|
||||
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')
|
||||
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_hash_int = tx_lock_refund.sha256
|
||||
@@ -696,7 +744,7 @@ class BTCInterface(Secp256k1Interface):
|
||||
ensure(locked_coin == swap_value, 'Bad locked value')
|
||||
|
||||
# Check script
|
||||
A, B = extractScriptLockScriptValues(script_out)
|
||||
A, B = self.extractScriptLockScriptValues(script_out)
|
||||
ensure(A == Kal, 'Bad script pubkey')
|
||||
ensure(B == Kaf, 'Bad script pubkey')
|
||||
|
||||
@@ -709,7 +757,7 @@ class BTCInterface(Secp256k1Interface):
|
||||
for pi in tx.vin:
|
||||
ptx = self.rpc('getrawtransaction', [i2h(pi.prevout.hash), True])
|
||||
prevout = ptx['vout'][pi.prevout.n]
|
||||
inputs_value += self.make_int(prevout['value'])
|
||||
inputs_value += make_int(prevout['value'])
|
||||
|
||||
prevout_type = prevout['scriptPubKey']['type']
|
||||
if prevout_type == 'witness_v0_keyhash':
|
||||
@@ -764,7 +812,7 @@ class BTCInterface(Secp256k1Interface):
|
||||
locked_coin = tx.vout[locked_n].nValue
|
||||
|
||||
# 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(B == Kaf, 'Bad script pubkey')
|
||||
ensure(csv_val == csv_val_expect, 'Bad script csv value')
|
||||
@@ -876,30 +924,27 @@ class BTCInterface(Secp256k1Interface):
|
||||
|
||||
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)
|
||||
sig_hash = SegwitV0SignatureHash(prevout_script, tx, input_n, SIGHASH_ALL, prevout_value)
|
||||
|
||||
eck = PrivateKey(key_bytes)
|
||||
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)
|
||||
sig_hash = SegwitV0SignatureHash(prevout_script, tx, input_n, SIGHASH_ALL, prevout_value)
|
||||
|
||||
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)
|
||||
sig_hash = SegwitV0SignatureHash(prevout_script, tx, input_n, SIGHASH_ALL, prevout_value)
|
||||
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,))
|
||||
|
||||
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:
|
||||
tx = self.loadTx(tx_bytes)
|
||||
sig_hash = SegwitV0SignatureHash(prevout_script, tx, input_n, SIGHASH_ALL, prevout_value)
|
||||
@@ -907,7 +952,11 @@ class BTCInterface(Secp256k1Interface):
|
||||
pubkey = PublicKey(K)
|
||||
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)
|
||||
# TODO: unlock unspents if bid cancelled
|
||||
options = {
|
||||
@@ -917,7 +966,7 @@ class BTCInterface(Secp256k1Interface):
|
||||
rv = self.rpc_wallet('fundrawtransaction', [tx.hex(), options])
|
||||
return bytes.fromhex(rv['hex'])
|
||||
|
||||
def listInputs(self, tx_bytes: bytes):
|
||||
def listInputs(self, tx_bytes):
|
||||
tx = self.loadTx(tx_bytes)
|
||||
|
||||
all_locked = self.rpc_wallet('listlockunspent')
|
||||
@@ -969,20 +1018,20 @@ class BTCInterface(Secp256k1Interface):
|
||||
return hash160(K)
|
||||
|
||||
def getScriptDest(self, script):
|
||||
return CScript([OP_0, sha256(script)])
|
||||
return CScript([OP_0, hashlib.sha256(script).digest()])
|
||||
|
||||
def getScriptScriptSig(self, script: bytes) -> bytes:
|
||||
return bytes()
|
||||
|
||||
def getP2SHP2WSHDest(self, script):
|
||||
script_hash = sha256(script)
|
||||
script_hash = hashlib.sha256(script).digest()
|
||||
assert len(script_hash) == 32
|
||||
p2wsh_hash = hash160(CScript([OP_0, script_hash]))
|
||||
assert len(p2wsh_hash) == 20
|
||||
return CScript([OP_HASH160, p2wsh_hash, OP_EQUAL])
|
||||
|
||||
def getP2SHP2WSHScriptSig(self, script):
|
||||
script_hash = sha256(script)
|
||||
script_hash = hashlib.sha256(script).digest()
|
||||
assert len(script_hash) == 32
|
||||
return CScript([CScript([OP_0, script_hash, ]), ])
|
||||
|
||||
@@ -1001,7 +1050,7 @@ class BTCInterface(Secp256k1Interface):
|
||||
|
||||
def getWalletTransaction(self, txid: bytes):
|
||||
try:
|
||||
return bytes.fromhex(self.rpc_wallet('gettransaction', [txid.hex()]))
|
||||
return bytes.fromhex(self.rpc('gettransaction', [txid.hex()]))
|
||||
except Exception as ex:
|
||||
# TODO: filter errors
|
||||
return None
|
||||
@@ -1023,11 +1072,11 @@ class BTCInterface(Secp256k1Interface):
|
||||
tx.wit.vtxinwit.clear()
|
||||
return tx.serialize()
|
||||
|
||||
def extractLeaderSig(self, tx_bytes: bytes) -> bytes:
|
||||
def extractLeaderSig(self, tx_bytes) -> bytes:
|
||||
tx = self.loadTx(tx_bytes)
|
||||
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)
|
||||
return tx.wit.vtxinwit[0].scriptWitness.stack[2]
|
||||
|
||||
@@ -1041,7 +1090,7 @@ class BTCInterface(Secp256k1Interface):
|
||||
def encodeSharedAddress(self, Kbv, 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.fundTx(b_lock_tx, feerate)
|
||||
@@ -1050,6 +1099,9 @@ class BTCInterface(Secp256k1Interface):
|
||||
|
||||
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:
|
||||
wsf = self.witnessScaleFactor()
|
||||
len_full = len(tx.serialize_with_witness()) + add_bytes + add_witness_bytes
|
||||
@@ -1079,10 +1131,10 @@ class BTCInterface(Secp256k1Interface):
|
||||
witness_bytes = 109
|
||||
vsize = self.getTxVSize(tx, add_witness_bytes=witness_bytes)
|
||||
pay_fee = round(fee_rate * vsize / 1000)
|
||||
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
|
||||
|
||||
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())
|
||||
wtx = self.rpc_wallet('gettransaction', [chain_b_lock_txid.hex(), ])
|
||||
lock_tx = self.loadTx(bytes.fromhex(wtx['hex']))
|
||||
@@ -1097,7 +1149,7 @@ class BTCInterface(Secp256k1Interface):
|
||||
tx.nVersion = self.txVersion()
|
||||
|
||||
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),
|
||||
nSequence=0,
|
||||
@@ -1119,11 +1171,11 @@ class BTCInterface(Secp256k1Interface):
|
||||
addr_info = self.rpc_wallet('getaddressinfo', [address])
|
||||
return addr_info['iswatchonly']
|
||||
|
||||
def getSCLockScriptAddress(self, lock_script: bytes) -> str:
|
||||
def getSCLockScriptAddress(self, lock_script):
|
||||
lock_tx_dest = self.getScriptDest(lock_script)
|
||||
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
|
||||
|
||||
if not self.isAddressMine(dest_address, or_watch_only=True):
|
||||
@@ -1192,30 +1244,30 @@ class BTCInterface(Secp256k1Interface):
|
||||
'vout': utxo['vout']})
|
||||
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]
|
||||
return self.rpc_wallet('sendtoaddress', params)
|
||||
|
||||
def signCompact(self, k, message: str) -> bytes:
|
||||
message_hash = sha256(bytes(message, 'utf-8'))
|
||||
def signCompact(self, k, message):
|
||||
message_hash = hashlib.sha256(bytes(message, 'utf-8')).digest()
|
||||
|
||||
privkey = PrivateKey(k)
|
||||
return privkey.sign_recoverable(message_hash, hasher=None)[:64]
|
||||
|
||||
def signRecoverable(self, k, message: str) -> bytes:
|
||||
message_hash = sha256(bytes(message, 'utf-8'))
|
||||
def signRecoverable(self, k, message):
|
||||
message_hash = hashlib.sha256(bytes(message, 'utf-8')).digest()
|
||||
|
||||
privkey = PrivateKey(k)
|
||||
return privkey.sign_recoverable(message_hash, hasher=None)
|
||||
|
||||
def verifyCompactSig(self, K, message: str, sig) -> None:
|
||||
message_hash = sha256(bytes(message, 'utf-8'))
|
||||
def verifyCompactSig(self, K, message, sig):
|
||||
message_hash = hashlib.sha256(bytes(message, 'utf-8')).digest()
|
||||
pubkey = PublicKey(K)
|
||||
rv = pubkey.verify_compact(sig, message_hash, hasher=None)
|
||||
assert (rv is True)
|
||||
|
||||
def verifySigAndRecover(self, sig, message: str) -> bytes:
|
||||
message_hash = sha256(bytes(message, 'utf-8'))
|
||||
def verifySigAndRecover(self, sig, message):
|
||||
message_hash = hashlib.sha256(bytes(message, 'utf-8')).digest()
|
||||
pubkey = PublicKey.from_signature_and_message(sig, message_hash, hasher=None)
|
||||
return pubkey.format()
|
||||
|
||||
@@ -1224,7 +1276,7 @@ class BTCInterface(Secp256k1Interface):
|
||||
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_hash = sha256(sha256(message_bytes))
|
||||
message_hash = hashlib.sha256(hashlib.sha256(message_bytes).digest()).digest()
|
||||
signature_bytes = base64.b64decode(signature)
|
||||
rec_id = (signature_bytes[0] - 27) & 3
|
||||
signature_bytes = signature_bytes[1:] + bytes((rec_id,))
|
||||
@@ -1242,6 +1294,40 @@ class BTCInterface(Secp256k1Interface):
|
||||
def showLockTransfers(self, kbv, Kbs, restore_height):
|
||||
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):
|
||||
length = getCompactSizeLen(len(witness_stack))
|
||||
for e in witness_stack:
|
||||
@@ -1290,7 +1376,7 @@ class BTCInterface(Secp256k1Interface):
|
||||
unspent_addr = dict()
|
||||
unspent = self.rpc_wallet('listunspent')
|
||||
for u in unspent:
|
||||
if u.get('spendable', False) is False:
|
||||
if u['spendable'] is not True:
|
||||
continue
|
||||
if 'address' not in u:
|
||||
continue
|
||||
@@ -1323,6 +1409,7 @@ class BTCInterface(Secp256k1Interface):
|
||||
def getProofOfFunds(self, amount_for, extra_commit_bytes):
|
||||
# TODO: Lock unspent and use same output/s to fund bid
|
||||
unspent_addr = self.getUnspentsByAddr()
|
||||
|
||||
sign_for_addr = None
|
||||
for addr, value in unspent_addr.items():
|
||||
if value >= amount_for:
|
||||
@@ -1344,12 +1431,6 @@ class BTCInterface(Secp256k1Interface):
|
||||
prove_utxos = [] # TODO: Send specific 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):
|
||||
proof_utxos = []
|
||||
if len(msg_utxos) > 0:
|
||||
@@ -1379,7 +1460,7 @@ class BTCInterface(Secp256k1Interface):
|
||||
return True
|
||||
return False
|
||||
|
||||
def isWalletEncryptedLocked(self) -> (bool, bool):
|
||||
def isWalletEncryptedLocked(self):
|
||||
wallet_info = self.rpc_wallet('getwalletinfo')
|
||||
encrypted = 'unlocked_until' in wallet_info
|
||||
locked = encrypted and wallet_info['unlocked_until'] <= 0
|
||||
@@ -1422,7 +1503,7 @@ class BTCInterface(Secp256k1Interface):
|
||||
return CScript([OP_HASH160, script_hash, OP_EQUAL])
|
||||
|
||||
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):
|
||||
# Only works for wallet txns
|
||||
@@ -1435,10 +1516,10 @@ class BTCInterface(Secp256k1Interface):
|
||||
return {'txid': txid_hex, 'amount': 0, 'height': rv['blockheight']}
|
||||
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.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'])))
|
||||
pkh = self.decodeAddress(output_addr)
|
||||
script = self.getScriptForPubkeyHash(pkh)
|
||||
@@ -1446,11 +1527,11 @@ class BTCInterface(Secp256k1Interface):
|
||||
tx.rehash()
|
||||
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.nVersion = self.txVersion()
|
||||
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,))
|
||||
pkh = self.decodeAddress(output_addr)
|
||||
script = self.getScriptForPubkeyHash(pkh)
|
||||
@@ -1470,30 +1551,6 @@ class BTCInterface(Secp256k1Interface):
|
||||
tx_vsize += 323 if redeem else 287
|
||||
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():
|
||||
print('TODO: testBTCInterface')
|
||||
|
||||
@@ -66,7 +66,7 @@ class DASHInterface(BTCInterface):
|
||||
add_bytes = 107
|
||||
size = len(tx.serialize_with_witness()) + add_bytes
|
||||
pay_fee = round(fee_rate * size / 1000)
|
||||
self._log.info(f'BLockSpendTx fee_rate, size, fee: {fee_rate}, {size}, {pay_fee}.')
|
||||
self._log.info(f'BLockSpendTx fee_rate, size, fee: {fee_rate}, {size}, {pay_fee}.')
|
||||
return pay_fee
|
||||
|
||||
def findTxnByHash(self, txid_hex: str):
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
|
||||
from .dcr import DCRInterface
|
||||
|
||||
__all__ = ['DCRInterface',]
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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()
|
||||
@@ -5,8 +5,8 @@
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
import hashlib
|
||||
import random
|
||||
import hashlib
|
||||
|
||||
from .btc import BTCInterface, find_vout_for_address_from_txobj
|
||||
from basicswap.util import (
|
||||
@@ -42,6 +42,9 @@ class FIROInterface(BTCInterface):
|
||||
# No multiwallet support
|
||||
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):
|
||||
return 'zcoin'
|
||||
|
||||
@@ -49,9 +52,6 @@ class FIROInterface(BTCInterface):
|
||||
# load with -hdseed= parameter
|
||||
pass
|
||||
|
||||
def checkWallets(self) -> int:
|
||||
return 1
|
||||
|
||||
def getNewAddress(self, use_segwit, label='swap_receive'):
|
||||
return 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'] or addr_info['iswatchonly']
|
||||
|
||||
def getSCLockScriptAddress(self, lock_script: bytes) -> str:
|
||||
def getSCLockScriptAddress(self, lock_script):
|
||||
lock_tx_dest = self.getScriptDest(lock_script)
|
||||
address = self.encodeScriptDest(lock_tx_dest)
|
||||
|
||||
@@ -87,7 +87,7 @@ class FIROInterface(BTCInterface):
|
||||
|
||||
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
|
||||
|
||||
if not self.isAddressMine(dest_address, or_watch_only=True):
|
||||
@@ -201,7 +201,7 @@ class FIROInterface(BTCInterface):
|
||||
add_bytes = 107
|
||||
size = len(tx.serialize_with_witness()) + add_bytes
|
||||
pay_fee = round(fee_rate * size / 1000)
|
||||
self._log.info(f'BLockSpendTx fee_rate, size, fee: {fee_rate}, {size}, {pay_fee}.')
|
||||
self._log.info(f'BLockSpendTx fee_rate, size, fee: {fee_rate}, {size}, {pay_fee}.')
|
||||
return pay_fee
|
||||
|
||||
def signTxWithKey(self, tx: bytes, key: bytes) -> bytes:
|
||||
@@ -277,6 +277,8 @@ class FIROInterface(BTCInterface):
|
||||
break
|
||||
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
|
||||
# 'Address does not refer to key' for non p2pkh
|
||||
pkh = self.decodeAddress(sign_for_addr)
|
||||
@@ -337,7 +339,7 @@ class FIROInterface(BTCInterface):
|
||||
return
|
||||
current_height -= 1
|
||||
|
||||
def getBlockWithTxns(self, block_hash: str):
|
||||
def getBlockWithTxns(self, block_hash):
|
||||
# TODO: Bypass decoderawtransaction and getblockheader
|
||||
block = self.rpc('getblock', [block_hash, False])
|
||||
block_header = self.rpc('getblockheader', [block_hash])
|
||||
@@ -355,11 +357,9 @@ class FIROInterface(BTCInterface):
|
||||
|
||||
block_rv = {
|
||||
'hash': block_hash,
|
||||
'previousblockhash': block_header['previousblockhash'],
|
||||
'tx': tx_rv,
|
||||
'confirmations': block_header['confirmations'],
|
||||
'height': block_header['height'],
|
||||
'time': block_header['time'],
|
||||
'version': block_header['version'],
|
||||
'merkleroot': block_header['merkleroot'],
|
||||
}
|
||||
|
||||
@@ -32,16 +32,6 @@ class LTCInterface(BTCInterface):
|
||||
return self.rpc_wallet_mweb('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):
|
||||
rv = super(LTCInterface, self).getWalletInfo()
|
||||
|
||||
@@ -49,32 +39,14 @@ class LTCInterface(BTCInterface):
|
||||
rv['mweb_balance'] = mweb_info['balance']
|
||||
rv['mweb_unconfirmed'] = mweb_info['unconfirmed_balance']
|
||||
rv['mweb_immature'] = mweb_info['immature_balance']
|
||||
return rv
|
||||
|
||||
def getUnspentsByAddr(self):
|
||||
unspent_addr = dict()
|
||||
unspent = self.rpc_wallet('listunspent')
|
||||
for u in unspent:
|
||||
if u.get('spendable', False) is False:
|
||||
continue
|
||||
if u.get('solvable', False) is False: # Filter out mweb outputs
|
||||
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
|
||||
# Add unconfirmed mweb -> plain txns to the unconfirmed_balance
|
||||
txns = self.rpc_wallet('listtransactions')
|
||||
for tx in reversed(txns):
|
||||
amount: float = tx.get('amount', 0.0)
|
||||
if tx['confirmations'] == 0 and tx.get('mweb_out', None) and amount > 0.0:
|
||||
rv['unconfirmed_balance'] += amount
|
||||
return rv
|
||||
|
||||
|
||||
class LTCInterfaceMWEB(LTCInterface):
|
||||
|
||||
@@ -13,12 +13,7 @@ from coincurve.keys import (
|
||||
PublicKey,
|
||||
PrivateKey,
|
||||
)
|
||||
from basicswap.interface.btc import (
|
||||
BTCInterface,
|
||||
extractScriptLockRefundScriptValues,
|
||||
findOutput,
|
||||
find_vout_for_address_from_txobj,
|
||||
)
|
||||
from .btc import BTCInterface, find_vout_for_address_from_txobj, findOutput
|
||||
from basicswap.rpc import make_rpc_func
|
||||
from basicswap.chainparams import Coins
|
||||
from basicswap.interface.contrib.nav_test_framework.mininode import (
|
||||
@@ -29,6 +24,7 @@ from basicswap.interface.contrib.nav_test_framework.mininode import (
|
||||
CTransaction,
|
||||
CTxInWitness,
|
||||
FromHex,
|
||||
uint256_from_str,
|
||||
)
|
||||
from basicswap.util.crypto import hash160
|
||||
from basicswap.util.address import (
|
||||
@@ -37,7 +33,7 @@ from basicswap.util.address import (
|
||||
encodeAddress,
|
||||
)
|
||||
from basicswap.util import (
|
||||
b2i, i2b, i2h,
|
||||
i2b, i2h,
|
||||
ensure,
|
||||
)
|
||||
from basicswap.basicswap_util import (
|
||||
@@ -73,20 +69,20 @@ class NAVInterface(BTCInterface):
|
||||
# No multiwallet support
|
||||
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:
|
||||
# p2sh-p2wsh
|
||||
return True
|
||||
|
||||
def seedToMnemonic(self, key: bytes) -> None:
|
||||
def seedToMnemonic(self, key):
|
||||
return Mnemonic('english').to_mnemonic(key)
|
||||
|
||||
def initialiseWallet(self, key):
|
||||
# Load with -importmnemonic= parameter
|
||||
# load with -importmnemonic= parameter
|
||||
pass
|
||||
|
||||
def checkWallets(self) -> int:
|
||||
return 1
|
||||
|
||||
def getWalletSeedID(self):
|
||||
return self.rpc('getwalletinfo')['hdmasterkeyid']
|
||||
|
||||
@@ -220,6 +216,8 @@ class NAVInterface(BTCInterface):
|
||||
break
|
||||
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
|
||||
# 'Address does not refer to key' for non p2pkh
|
||||
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:
|
||||
tx = CTransaction()
|
||||
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']),
|
||||
scriptSig=self.getScriptScriptSig(txn_script)))
|
||||
@@ -323,7 +321,7 @@ class NAVInterface(BTCInterface):
|
||||
tx = CTransaction()
|
||||
tx.nVersion = self.txVersion()
|
||||
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,
|
||||
scriptSig=self.getScriptScriptSig(txn_script)))
|
||||
@@ -419,7 +417,7 @@ class NAVInterface(BTCInterface):
|
||||
return
|
||||
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
|
||||
|
||||
if not self.isAddressMine(dest_address, or_watch_only=True):
|
||||
@@ -483,18 +481,16 @@ class NAVInterface(BTCInterface):
|
||||
|
||||
block_rv = {
|
||||
'hash': block_hash,
|
||||
'previousblockhash': block_header['previousblockhash'],
|
||||
'tx': tx_rv,
|
||||
'confirmations': block_header['confirmations'],
|
||||
'height': block_header['height'],
|
||||
'time': block_header['time'],
|
||||
'version': block_header['version'],
|
||||
'merkleroot': block_header['merkleroot'],
|
||||
}
|
||||
|
||||
return block_rv
|
||||
|
||||
def getScriptScriptSig(self, script: bytes) -> bytes:
|
||||
def getScriptScriptSig(self, script: bytes) -> bytearray:
|
||||
return self.getP2SHP2WSHScriptSig(script)
|
||||
|
||||
def getScriptDest(self, script):
|
||||
@@ -516,7 +512,7 @@ class NAVInterface(BTCInterface):
|
||||
tx.vout.append(self.txoType()(output_amount, script_pk))
|
||||
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())
|
||||
wtx = self.rpc('gettransaction', [chain_b_lock_txid.hex(), ])
|
||||
lock_tx = self.loadTx(bytes.fromhex(wtx['hex']))
|
||||
@@ -530,7 +526,7 @@ class NAVInterface(BTCInterface):
|
||||
tx = CTransaction()
|
||||
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))
|
||||
|
||||
@@ -682,7 +678,7 @@ class NAVInterface(BTCInterface):
|
||||
ensure(locked_n is not None, 'Output not found in tx')
|
||||
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_hash_int = tx_lock_refund.sha256
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
|
||||
from .btc import BTCInterface
|
||||
from basicswap.chainparams import Coins
|
||||
from basicswap.util import (
|
||||
make_int,
|
||||
)
|
||||
|
||||
|
||||
class NMCInterface(BTCInterface):
|
||||
@@ -14,7 +17,7 @@ class NMCInterface(BTCInterface):
|
||||
def coin_type():
|
||||
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
|
||||
ro = self.rpc('scantxoutset', ['start', ['addr({})'.format(dest_address)]]) # TODO: Use combo(address) where possible
|
||||
self._log.debug('[rm] scantxoutset end')
|
||||
@@ -23,7 +26,7 @@ class NMCInterface(BTCInterface):
|
||||
if txid and o['txid'] != txid.hex():
|
||||
continue
|
||||
# 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'])
|
||||
continue
|
||||
|
||||
|
||||
@@ -14,10 +14,11 @@ from basicswap.contrib.test_framework.messages import (
|
||||
from basicswap.contrib.test_framework.script import (
|
||||
CScript,
|
||||
OP_0,
|
||||
OP_DUP, OP_HASH160, OP_EQUALVERIFY, OP_CHECKSIG,
|
||||
OP_DUP, OP_HASH160, OP_EQUALVERIFY, OP_CHECKSIG
|
||||
)
|
||||
from basicswap.util import (
|
||||
ensure,
|
||||
make_int,
|
||||
TemporaryError,
|
||||
)
|
||||
from basicswap.util.script import (
|
||||
@@ -26,15 +27,10 @@ from basicswap.util.script import (
|
||||
getWitnessElementLen,
|
||||
)
|
||||
from basicswap.util.address import (
|
||||
encodeStealthAddress,
|
||||
)
|
||||
from basicswap.interface.btc import (
|
||||
BTCInterface,
|
||||
extractScriptLockScriptValues,
|
||||
extractScriptLockRefundScriptValues,
|
||||
)
|
||||
|
||||
toWIF,
|
||||
encodeStealthAddress)
|
||||
from basicswap.chainparams import Coins, chainparams
|
||||
from .btc import BTCInterface
|
||||
|
||||
|
||||
class BalanceTypes(IntEnum):
|
||||
@@ -78,9 +74,6 @@ class PARTInterface(BTCInterface):
|
||||
super().__init__(coin_settings, network, swap_client)
|
||||
self.setAnonTxRingSize(int(coin_settings.get('anon_tx_ring_size', 12)))
|
||||
|
||||
def use_tx_vsize(self) -> bool:
|
||||
return True
|
||||
|
||||
def setAnonTxRingSize(self, value):
|
||||
ensure(value >= 3 and value < 33, 'Invalid 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')
|
||||
return index_info['spentindex']
|
||||
|
||||
def initialiseWallet(self, key: bytes) -> None:
|
||||
def initialiseWallet(self, key):
|
||||
raise ValueError('TODO')
|
||||
|
||||
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')
|
||||
|
||||
# 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')
|
||||
|
||||
# Check script
|
||||
lock_txo_scriptpk = bytes.fromhex(lock_tx_obj['vout'][lock_output_n]['scriptPubKey']['hex'])
|
||||
script_pk = CScript([OP_0, hashlib.sha256(script_out).digest()])
|
||||
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(B == Kaf, 'Bad script follower pubkey')
|
||||
|
||||
# TODO: Check that inputs are unspent, rangeproofs and commitments sum
|
||||
# Verify fee rate
|
||||
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
|
||||
|
||||
@@ -401,13 +394,13 @@ class PARTInterfaceBlind(PARTInterface):
|
||||
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')
|
||||
|
||||
lock_refund_txo_value = self.make_int(blinded_info['amount'])
|
||||
lock_refund_txo_value = make_int(blinded_info['amount'])
|
||||
|
||||
# Check script
|
||||
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()])
|
||||
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(B == Kaf, 'Bad script pubkey')
|
||||
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')
|
||||
|
||||
# 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')
|
||||
|
||||
# Check fee rate
|
||||
@@ -470,7 +463,7 @@ class PARTInterfaceBlind(PARTInterface):
|
||||
dummy_witness_stack = self.getScriptLockRefundSpendTxDummyWitness(prevout_script)
|
||||
witness_bytes = self.getWitnessStackSerialisedLength(dummy_witness_stack)
|
||||
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
|
||||
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])
|
||||
lock_spend_tx_hex = rv['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
|
||||
witness_bytes = self.getWitnessStackSerialisedLength(dummy_witness_stack)
|
||||
@@ -606,8 +599,8 @@ class PARTInterfaceBlind(PARTInterface):
|
||||
ensure(rv['inputs_valid'] is True, 'Invalid inputs')
|
||||
|
||||
# Check amount
|
||||
fee_paid = self.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'])
|
||||
fee_paid = make_int(lock_spend_tx_obj['vout'][0]['ct_fee'])
|
||||
amount_difference = make_int(input_blinded_info['amount']) - make_int(output_blinded_info['amount'])
|
||||
ensure(fee_paid == amount_difference, 'Invalid output amount')
|
||||
|
||||
# Check fee
|
||||
@@ -637,7 +630,7 @@ class PARTInterfaceBlind(PARTInterface):
|
||||
addr_info = self.rpc_wallet('getaddressinfo', [addr_out])
|
||||
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
|
||||
|
||||
@@ -671,7 +664,7 @@ class PARTInterfaceBlind(PARTInterface):
|
||||
def getSpendableBalance(self) -> int:
|
||||
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)
|
||||
sx_addr = self.formatStealthAddress(Kbv, Kbs)
|
||||
self._log.debug('sx_addr: {}'.format(sx_addr))
|
||||
@@ -695,7 +688,8 @@ class PARTInterfaceBlind(PARTInterface):
|
||||
else:
|
||||
addr_info = self.rpc_wallet('getaddressinfo', [sx_addr])
|
||||
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._log.info('Imported watch-only sx_addr: {}'.format(sx_addr))
|
||||
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
|
||||
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
|
||||
if tx['confirmations'] > 0:
|
||||
chain_height = self.rpc('getblockcount')
|
||||
@@ -720,14 +714,15 @@ class PARTInterfaceBlind(PARTInterface):
|
||||
return -1
|
||||
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)
|
||||
Kbs = self.getPubkey(kbs)
|
||||
sx_addr = self.formatStealthAddress(Kbv, Kbs)
|
||||
addr_info = self.rpc_wallet('getaddressinfo', [sx_addr])
|
||||
if not addr_info['ismine']:
|
||||
wif_scan_key = self.encodeKey(kbv)
|
||||
wif_spend_key = self.encodeKey(kbs)
|
||||
wif_prefix = self.chainparams_network()['key_prefix']
|
||||
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._log.info('Imported spend key for sx_addr: {}'.format(sx_addr))
|
||||
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')
|
||||
|
||||
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:
|
||||
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:
|
||||
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)
|
||||
sx_addr = self.formatStealthAddress(Kbv, Kbs)
|
||||
|
||||
@@ -831,7 +826,8 @@ class PARTInterfaceAnon(PARTInterface):
|
||||
else:
|
||||
addr_info = self.rpc_wallet('getaddressinfo', [sx_addr])
|
||||
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._log.info('Imported watch-only sx_addr: {}'.format(sx_addr))
|
||||
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
|
||||
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
|
||||
if tx['confirmations'] > 0:
|
||||
chain_height = self.rpc('getblockcount')
|
||||
@@ -856,14 +852,15 @@ class PARTInterfaceAnon(PARTInterface):
|
||||
return -1
|
||||
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)
|
||||
Kbs = self.getPubkey(kbs)
|
||||
sx_addr = self.formatStealthAddress(Kbv, Kbs)
|
||||
addr_info = self.rpc_wallet('getaddressinfo', [sx_addr])
|
||||
if not addr_info['ismine']:
|
||||
wif_scan_key = self.encodeKey(kbv)
|
||||
wif_spend_key = self.encodeKey(kbs)
|
||||
wif_prefix = self.chainparams_network()['key_prefix']
|
||||
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._log.info('Imported spend key for sx_addr: {}'.format(sx_addr))
|
||||
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')
|
||||
|
||||
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:
|
||||
self._log.warning('Spending actual balance {}, not swap value {}.'.format(utxo_sats, cb_swap_value))
|
||||
|
||||
@@ -75,11 +75,9 @@ class PIVXInterface(BTCInterface):
|
||||
|
||||
block_rv = {
|
||||
'hash': block_hash,
|
||||
'previousblockhash': block_header['previousblockhash'],
|
||||
'tx': tx_rv,
|
||||
'confirmations': block_header['confirmations'],
|
||||
'height': block_header['height'],
|
||||
'time': block_header['time'],
|
||||
'version': block_header['version'],
|
||||
'merkleroot': block_header['merkleroot'],
|
||||
}
|
||||
@@ -107,7 +105,7 @@ class PIVXInterface(BTCInterface):
|
||||
add_bytes = 107
|
||||
size = len(tx.serialize_with_witness()) + add_bytes
|
||||
pay_fee = round(fee_rate * size / 1000)
|
||||
self._log.info(f'BLockSpendTx fee_rate, size, fee: {fee_rate}, {size}, {pay_fee}.')
|
||||
self._log.info(f'BLockSpendTx fee_rate, size, fee: {fee_rate}, {size}, {pay_fee}.')
|
||||
return pay_fee
|
||||
|
||||
def signTxWithKey(self, tx: bytes, key: bytes) -> bytes:
|
||||
|
||||
@@ -24,21 +24,20 @@ from coincurve.dleag import (
|
||||
verify_ed25519_point,
|
||||
)
|
||||
|
||||
from basicswap.interface.base import (
|
||||
Curves,
|
||||
)
|
||||
from basicswap.interface import (
|
||||
Curves)
|
||||
from basicswap.util import (
|
||||
i2b, b2i, b2h,
|
||||
dumpj,
|
||||
ensure,
|
||||
make_int,
|
||||
TemporaryError)
|
||||
from basicswap.util.network import (
|
||||
is_private_ip_address)
|
||||
from basicswap.rpc_xmr import (
|
||||
make_xmr_rpc_func,
|
||||
make_xmr_rpc2_func)
|
||||
from basicswap.chainparams import XMR_COIN, Coins
|
||||
from basicswap.interface.base import CoinInterface
|
||||
from basicswap.chainparams import XMR_COIN, CoinInterface, Coins
|
||||
|
||||
|
||||
class XMRInterface(CoinInterface):
|
||||
@@ -77,13 +76,11 @@ class XMRInterface(CoinInterface):
|
||||
@staticmethod
|
||||
def xmr_swap_b_lock_spend_tx_vsize() -> int:
|
||||
# TODO: Estimate with ringsize
|
||||
return 1604
|
||||
return 1507
|
||||
|
||||
def __init__(self, coin_settings, network, swap_client=None):
|
||||
super().__init__(network)
|
||||
|
||||
self._addr_prefix = self.chainparams_network()['address_prefix']
|
||||
|
||||
self.blocks_confirmed = coin_settings['blocks_confirmed']
|
||||
self._restore_height = coin_settings.get('restore_height', 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.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):
|
||||
ensure(new_priority >= 0 and new_priority < 4, 'Invalid fee_priority value')
|
||||
self._fee_priority = new_priority
|
||||
@@ -154,7 +154,7 @@ class XMRInterface(CoinInterface):
|
||||
pass
|
||||
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:
|
||||
try:
|
||||
self.openWallet(self._wallet_filename)
|
||||
@@ -165,7 +165,7 @@ class XMRInterface(CoinInterface):
|
||||
|
||||
Kbv = self.getPubkey(key_view)
|
||||
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 = {
|
||||
'filename': self._wallet_filename,
|
||||
@@ -231,13 +231,15 @@ class XMRInterface(CoinInterface):
|
||||
rv = {}
|
||||
self.rpc_wallet('refresh')
|
||||
balance_info = self.rpc_wallet('get_balance')
|
||||
|
||||
rv['balance'] = self.format_amount(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['locked'] = False
|
||||
return rv
|
||||
|
||||
def walletRestoreHeight(self):
|
||||
return self._restore_height
|
||||
|
||||
def getMainWalletAddress(self) -> str:
|
||||
with self._mx_wallet:
|
||||
self.openWallet(self._wallet_filename)
|
||||
@@ -251,15 +253,8 @@ class XMRInterface(CoinInterface):
|
||||
return new_address
|
||||
|
||||
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].
|
||||
fee_est = self.rpc('get_fee_estimate')
|
||||
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'
|
||||
self._log.warning('TODO - estimate XMR fee rate?')
|
||||
return 0.0, 'unused'
|
||||
|
||||
def getNewSecretKey(self) -> bytes:
|
||||
# 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:
|
||||
pk_view = self.getPubkey(key_view)
|
||||
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:
|
||||
i = b2i(k)
|
||||
@@ -314,15 +309,15 @@ class XMRInterface(CoinInterface):
|
||||
return ed25519_add(Ka, Kb)
|
||||
|
||||
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:
|
||||
self.openWallet(self._wallet_filename)
|
||||
self.rpc_wallet('refresh')
|
||||
|
||||
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}
|
||||
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)
|
||||
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
|
||||
|
||||
def findTxB(self, kbv, Kbs, cb_swap_value, cb_block_confirmed, restore_height, bid_sender):
|
||||
with self._mx_wallet:
|
||||
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]
|
||||
params = {
|
||||
@@ -406,7 +413,7 @@ class XMRInterface(CoinInterface):
|
||||
|
||||
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:
|
||||
"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:
|
||||
Kbv = self.getPubkey(kbv)
|
||||
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'
|
||||
|
||||
@@ -466,42 +473,36 @@ class XMRInterface(CoinInterface):
|
||||
|
||||
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:
|
||||
value_sats = make_int(value, self.exp())
|
||||
|
||||
self.openWallet(self._wallet_filename)
|
||||
self.rpc_wallet('refresh')
|
||||
|
||||
if sweepall:
|
||||
if subfee:
|
||||
balance = self.rpc_wallet('get_balance')
|
||||
if balance['balance'] != balance['unlocked_balance']:
|
||||
raise ValueError('Balance must be fully confirmed to use sweep all.')
|
||||
self._log.info('XMR {} sweep_all.'.format('estimate fee' if estimate_fee else 'withdraw'))
|
||||
self._log.debug('XMR balance: {}'.format(balance['balance']))
|
||||
params = {'address': addr_to, 'do_not_relay': estimate_fee}
|
||||
if self._fee_priority > 0:
|
||||
params['priority'] = self._fee_priority
|
||||
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]
|
||||
diff = balance['unlocked_balance'] - value_sats
|
||||
if diff >= 0 and diff <= 10:
|
||||
self._log.info('subfee enabled and value close to total, using sweep_all.')
|
||||
params = {'address': addr_to}
|
||||
if self._fee_priority > 0:
|
||||
params['priority'] = self._fee_priority
|
||||
rv = self.rpc_wallet('sweep_all', params)
|
||||
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}], 'do_not_relay': estimate_fee}
|
||||
params = {'destinations': [{'amount': value_sats, 'address': addr_to}]}
|
||||
if self._fee_priority > 0:
|
||||
params['priority'] = self._fee_priority
|
||||
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']
|
||||
|
||||
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):
|
||||
with self._mx_wallet:
|
||||
try:
|
||||
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'
|
||||
try:
|
||||
self.openWallet(wallet_file)
|
||||
|
||||
@@ -52,20 +52,12 @@ def getFormData(post_string: str, is_json: bool):
|
||||
|
||||
def withdraw_coin(swap_client, coin_type, 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')
|
||||
subfee = get_data_entry(post_data, 'subfee')
|
||||
if not isinstance(subfee, bool):
|
||||
subfee = toBool(subfee)
|
||||
value = get_data_entry(post_data, 'value')
|
||||
address = get_data_entry(post_data, 'address')
|
||||
subfee = get_data_entry(post_data, 'subfee')
|
||||
if not isinstance(subfee, bool):
|
||||
subfee = toBool(subfee)
|
||||
|
||||
if coin_type == Coins.PART:
|
||||
type_from = get_data_entry_or(post_data, 'type_from', 'plain')
|
||||
@@ -74,8 +66,6 @@ def withdraw_coin(swap_client, coin_type, post_string, is_json):
|
||||
elif coin_type == Coins.LTC:
|
||||
type_from = get_data_entry_or(post_data, 'type_from', 'plain')
|
||||
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:
|
||||
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 = {
|
||||
'valid_for_seconds': valid_for_seconds,
|
||||
}
|
||||
|
||||
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'):
|
||||
if have_data_entry(post_data, 'bid_rate'):
|
||||
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'):
|
||||
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)
|
||||
return bytes(json.dumps({'amount_from': amount_from}), 'UTF-8')
|
||||
|
||||
amt_from: int = inputAmount(get_data_entry(post_data, 'amt_from'), ci_from)
|
||||
amt_to: int = inputAmount(get_data_entry(post_data, 'amt_to'), ci_to)
|
||||
amt_from = inputAmount(get_data_entry(post_data, 'amt_from'), ci_from)
|
||||
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')
|
||||
|
||||
|
||||
@@ -635,33 +622,6 @@ def js_automationstrategies(self, url_split, post_string: str, is_json: bool) ->
|
||||
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:
|
||||
swap_client = self.server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
@@ -777,7 +737,6 @@ pages = {
|
||||
'notifications': js_notifications,
|
||||
'identities': js_identities,
|
||||
'automationstrategies': js_automationstrategies,
|
||||
'validateamount': js_validateamount,
|
||||
'vacuumdb': js_vacuumdb,
|
||||
'getcoinseed': js_getcoinseed,
|
||||
'setpassword': js_setpassword,
|
||||
|
||||
@@ -4,13 +4,12 @@ package basicswap;
|
||||
|
||||
/* Step 1, seller -> network */
|
||||
message OfferMessage {
|
||||
uint32 protocol_version = 1;
|
||||
uint32 coin_from = 2;
|
||||
uint32 coin_to = 3;
|
||||
uint64 amount_from = 4;
|
||||
uint64 amount_to = 5;
|
||||
uint64 min_bid_amount = 6;
|
||||
uint64 time_valid = 7;
|
||||
uint32 coin_from = 1;
|
||||
uint32 coin_to = 2;
|
||||
uint64 amount_from = 3;
|
||||
uint64 rate = 4;
|
||||
uint64 min_bid_amount = 5;
|
||||
uint64 time_valid = 6;
|
||||
enum LockType {
|
||||
NOT_SET = 0;
|
||||
SEQUENCE_LOCK_BLOCKS = 1;
|
||||
@@ -18,19 +17,20 @@ message OfferMessage {
|
||||
ABS_LOCK_BLOCKS = 3;
|
||||
ABS_LOCK_TIME = 4;
|
||||
}
|
||||
LockType lock_type = 8;
|
||||
uint32 lock_value = 9;
|
||||
uint32 swap_type = 10;
|
||||
LockType lock_type = 7;
|
||||
uint32 lock_value = 8;
|
||||
uint32 swap_type = 9;
|
||||
|
||||
/* optional */
|
||||
string proof_address = 11;
|
||||
string proof_signature = 12;
|
||||
bytes pkhash_seller = 13;
|
||||
bytes secret_hash = 14;
|
||||
string proof_address = 10;
|
||||
string proof_signature = 11;
|
||||
bytes pkhash_seller = 12;
|
||||
bytes secret_hash = 13;
|
||||
|
||||
uint64 fee_rate_from = 15;
|
||||
uint64 fee_rate_to = 16;
|
||||
uint64 fee_rate_from = 14;
|
||||
uint64 fee_rate_to = 15;
|
||||
|
||||
uint32 protocol_version = 16;
|
||||
bool amount_negotiable = 17;
|
||||
bool rate_negotiable = 18;
|
||||
|
||||
@@ -39,36 +39,39 @@ message OfferMessage {
|
||||
|
||||
/* Step 2, buyer -> seller */
|
||||
message BidMessage {
|
||||
uint32 protocol_version = 1;
|
||||
bytes offer_msg_id = 2;
|
||||
uint64 time_valid = 3; /* seconds bid is valid for */
|
||||
uint64 amount = 4; /* amount of amount_from bid is for */
|
||||
uint64 amount_to = 5;
|
||||
bytes pkhash_buyer = 6; /* buyer's address to receive amount_from */
|
||||
string proof_address = 7;
|
||||
string proof_signature = 8;
|
||||
bytes offer_msg_id = 1;
|
||||
uint64 time_valid = 2; /* seconds bid is valid for */
|
||||
uint64 amount = 3; /* amount of amount_from bid is for */
|
||||
uint64 rate = 4;
|
||||
bytes pkhash_buyer = 5; /* buyer's address to receive amount_from */
|
||||
string proof_address = 6;
|
||||
string proof_signature = 7;
|
||||
|
||||
uint32 protocol_version = 8;
|
||||
|
||||
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 */
|
||||
message BidMessage_test {
|
||||
uint32 protocol_version = 1;
|
||||
bytes offer_msg_id = 2;
|
||||
uint64 time_valid = 3;
|
||||
uint64 amount = 4;
|
||||
uint64 rate = 5;
|
||||
message BidMessage_v1Deprecated {
|
||||
bytes offer_msg_id = 1;
|
||||
uint64 time_valid = 2; /* seconds bid is valid for */
|
||||
uint64 amount = 3; /* amount of amount_from bid is for */
|
||||
uint64 rate = 4;
|
||||
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 */
|
||||
message BidAcceptMessage {
|
||||
bytes bid_msg_id = 1;
|
||||
bytes initiate_txid = 2;
|
||||
bytes contract_script = 3;
|
||||
bytes pkhash_seller = 4;
|
||||
}
|
||||
|
||||
message OfferRevokeMessage {
|
||||
@@ -78,23 +81,25 @@ message OfferRevokeMessage {
|
||||
|
||||
message BidRejectMessage {
|
||||
bytes bid_msg_id = 1;
|
||||
|
||||
uint32 reject_code = 2;
|
||||
}
|
||||
|
||||
message XmrBidMessage {
|
||||
/* MSG1L, F -> L */
|
||||
uint32 protocol_version = 1;
|
||||
bytes offer_msg_id = 2;
|
||||
uint64 time_valid = 3; /* seconds bid is valid for */
|
||||
uint64 amount = 4; /* amount of amount_from bid is for */
|
||||
uint64 amount_to = 5;
|
||||
bytes offer_msg_id = 1;
|
||||
uint64 time_valid = 2; /* seconds bid is valid for */
|
||||
uint64 amount = 3; /* amount of amount_from bid is for */
|
||||
uint64 rate = 4;
|
||||
|
||||
bytes pkaf = 6;
|
||||
bytes pkaf = 5;
|
||||
|
||||
bytes kbvf = 7;
|
||||
bytes kbsf_dleag = 8;
|
||||
bytes kbvf = 6;
|
||||
bytes kbsf_dleag = 7;
|
||||
|
||||
bytes dest_af = 9;
|
||||
bytes dest_af = 8;
|
||||
|
||||
uint32 protocol_version = 9;
|
||||
}
|
||||
|
||||
message XmrSplitMessage {
|
||||
@@ -107,22 +112,24 @@ message XmrSplitMessage {
|
||||
message XmrBidAcceptMessage {
|
||||
bytes bid_msg_id = 1;
|
||||
|
||||
bytes pkal = 2;
|
||||
bytes kbvl = 3;
|
||||
bytes kbsl_dleag = 4;
|
||||
bytes pkal = 3;
|
||||
|
||||
bytes kbvl = 4;
|
||||
bytes kbsl_dleag = 5;
|
||||
|
||||
/* MSG2F */
|
||||
bytes a_lock_tx = 5;
|
||||
bytes a_lock_tx_script = 6;
|
||||
bytes a_lock_refund_tx = 7;
|
||||
bytes a_lock_refund_tx_script = 8;
|
||||
bytes a_lock_refund_spend_tx = 9;
|
||||
bytes al_lock_refund_tx_sig = 10;
|
||||
bytes a_lock_tx = 6;
|
||||
bytes a_lock_tx_script = 7;
|
||||
bytes a_lock_refund_tx = 8;
|
||||
bytes a_lock_refund_tx_script = 9;
|
||||
bytes a_lock_refund_spend_tx = 10;
|
||||
bytes al_lock_refund_tx_sig = 11;
|
||||
}
|
||||
|
||||
message XmrBidLockTxSigsMessage {
|
||||
/* MSG3L */
|
||||
bytes bid_msg_id = 1;
|
||||
|
||||
bytes af_lock_refund_spend_tx_esig = 2;
|
||||
bytes af_lock_refund_tx_sig = 3;
|
||||
}
|
||||
@@ -130,6 +137,7 @@ message XmrBidLockTxSigsMessage {
|
||||
message XmrBidLockSpendTxMessage {
|
||||
/* MSG4F */
|
||||
bytes bid_msg_id = 1;
|
||||
|
||||
bytes a_lock_spend_tx = 2;
|
||||
bytes kal_sig = 3;
|
||||
}
|
||||
@@ -137,16 +145,19 @@ message XmrBidLockSpendTxMessage {
|
||||
message XmrBidLockReleaseMessage {
|
||||
/* MSG5F */
|
||||
bytes bid_msg_id = 1;
|
||||
|
||||
bytes al_lock_spend_tx_esig = 2;
|
||||
}
|
||||
|
||||
message ADSBidIntentMessage {
|
||||
/* L -> F Sent from bidder, construct a reverse bid */
|
||||
uint32 protocol_version = 1;
|
||||
bytes offer_msg_id = 2;
|
||||
uint64 time_valid = 3; /* seconds bid is valid for */
|
||||
uint64 amount_from = 4; /* amount of offer.coin_from bid is for */
|
||||
uint64 amount_to = 5; /* amount of offer.coin_to bid is for, equivalent to bid.amount */
|
||||
bytes offer_msg_id = 1;
|
||||
uint64 time_valid = 2; /* seconds bid is valid for */
|
||||
uint64 amount_from = 3; /* 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 rate = 5; /* amount of offer.coin_from bid is for */
|
||||
|
||||
uint32 protocol_version = 6;
|
||||
}
|
||||
|
||||
message ADSBidIntentAcceptMessage {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# source: messages.proto
|
||||
# Protobuf Python Version: 4.25.3
|
||||
"""Generated protocol buffer code."""
|
||||
from google.protobuf import descriptor as _descriptor
|
||||
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()
|
||||
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
||||
@@ -22,33 +21,33 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'messages_pb2', _globals)
|
||||
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||
DESCRIPTOR._options = None
|
||||
_globals['_OFFERMESSAGE']._serialized_start=30
|
||||
_globals['_OFFERMESSAGE']._serialized_end=606
|
||||
_globals['_OFFERMESSAGE_LOCKTYPE']._serialized_start=493
|
||||
_globals['_OFFERMESSAGE_LOCKTYPE']._serialized_end=606
|
||||
_globals['_BIDMESSAGE']._serialized_start=609
|
||||
_globals['_BIDMESSAGE']._serialized_end=840
|
||||
_globals['_BIDMESSAGE_TEST']._serialized_start=842
|
||||
_globals['_BIDMESSAGE_TEST']._serialized_end=957
|
||||
_globals['_BIDACCEPTMESSAGE']._serialized_start=959
|
||||
_globals['_OFFERMESSAGE']._serialized_end=580
|
||||
_globals['_OFFERMESSAGE_LOCKTYPE']._serialized_start=467
|
||||
_globals['_OFFERMESSAGE_LOCKTYPE']._serialized_end=580
|
||||
_globals['_BIDMESSAGE']._serialized_start=583
|
||||
_globals['_BIDMESSAGE']._serialized_end=784
|
||||
_globals['_BIDMESSAGE_V1DEPRECATED']._serialized_start=787
|
||||
_globals['_BIDMESSAGE_V1DEPRECATED']._serialized_end=980
|
||||
_globals['_BIDACCEPTMESSAGE']._serialized_start=982
|
||||
_globals['_BIDACCEPTMESSAGE']._serialized_end=1068
|
||||
_globals['_OFFERREVOKEMESSAGE']._serialized_start=1070
|
||||
_globals['_OFFERREVOKEMESSAGE']._serialized_end=1131
|
||||
_globals['_BIDREJECTMESSAGE']._serialized_start=1133
|
||||
_globals['_BIDREJECTMESSAGE']._serialized_end=1192
|
||||
_globals['_XMRBIDMESSAGE']._serialized_start=1195
|
||||
_globals['_XMRBIDMESSAGE']._serialized_end=1378
|
||||
_globals['_XMRSPLITMESSAGE']._serialized_start=1380
|
||||
_globals['_XMRSPLITMESSAGE']._serialized_end=1464
|
||||
_globals['_XMRBIDACCEPTMESSAGE']._serialized_start=1467
|
||||
_globals['_XMRBIDACCEPTMESSAGE']._serialized_end=1723
|
||||
_globals['_XMRBIDLOCKTXSIGSMESSAGE']._serialized_start=1725
|
||||
_globals['_XMRBIDLOCKTXSIGSMESSAGE']._serialized_end=1839
|
||||
_globals['_XMRBIDLOCKSPENDTXMESSAGE']._serialized_start=1841
|
||||
_globals['_XMRBIDLOCKSPENDTXMESSAGE']._serialized_end=1929
|
||||
_globals['_XMRBIDLOCKRELEASEMESSAGE']._serialized_start=1931
|
||||
_globals['_XMRBIDLOCKRELEASEMESSAGE']._serialized_end=2008
|
||||
_globals['_ADSBIDINTENTMESSAGE']._serialized_start=2011
|
||||
_globals['_ADSBIDINTENTMESSAGE']._serialized_end=2140
|
||||
_globals['_ADSBIDINTENTACCEPTMESSAGE']._serialized_start=2142
|
||||
_globals['_ADSBIDINTENTACCEPTMESSAGE']._serialized_end=2254
|
||||
_globals['_XMRBIDMESSAGE']._serialized_end=1373
|
||||
_globals['_XMRSPLITMESSAGE']._serialized_start=1375
|
||||
_globals['_XMRSPLITMESSAGE']._serialized_end=1459
|
||||
_globals['_XMRBIDACCEPTMESSAGE']._serialized_start=1462
|
||||
_globals['_XMRBIDACCEPTMESSAGE']._serialized_end=1718
|
||||
_globals['_XMRBIDLOCKTXSIGSMESSAGE']._serialized_start=1720
|
||||
_globals['_XMRBIDLOCKTXSIGSMESSAGE']._serialized_end=1834
|
||||
_globals['_XMRBIDLOCKSPENDTXMESSAGE']._serialized_start=1836
|
||||
_globals['_XMRBIDLOCKSPENDTXMESSAGE']._serialized_end=1924
|
||||
_globals['_XMRBIDLOCKRELEASEMESSAGE']._serialized_start=1926
|
||||
_globals['_XMRBIDLOCKRELEASEMESSAGE']._serialized_end=2003
|
||||
_globals['_ADSBIDINTENTMESSAGE']._serialized_start=2006
|
||||
_globals['_ADSBIDINTENTMESSAGE']._serialized_end=2149
|
||||
_globals['_ADSBIDINTENTACCEPTMESSAGE']._serialized_start=2151
|
||||
_globals['_ADSBIDINTENTACCEPTMESSAGE']._serialized_end=2263
|
||||
# @@protoc_insertion_point(module_scope)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2020-2024 tecnovert
|
||||
# Copyright (c) 2020-2023 tecnovert
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
@@ -10,15 +10,12 @@ from basicswap.db import (
|
||||
from basicswap.util import (
|
||||
SerialiseNum,
|
||||
)
|
||||
from basicswap.util.script import (
|
||||
decodeScriptNum,
|
||||
)
|
||||
from basicswap.script import (
|
||||
OpCodes,
|
||||
)
|
||||
from basicswap.basicswap_util import (
|
||||
EventLogTypes,
|
||||
SwapTypes,
|
||||
EventLogTypes,
|
||||
)
|
||||
from . import ProtocolInterface
|
||||
|
||||
@@ -26,13 +23,13 @@ INITIATE_TX_TIMEOUT = 40 * 60 # TODO: make variable per coin
|
||||
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([
|
||||
OpCodes.OP_IF,
|
||||
OpCodes.OP_SIZE,
|
||||
0x01, 0x20, # 32
|
||||
OpCodes.OP_EQUALVERIFY,
|
||||
op_hash,
|
||||
OpCodes.OP_SHA256,
|
||||
0x20]) \
|
||||
+ secret_hash \
|
||||
+ bytearray([
|
||||
@@ -57,46 +54,6 @@ def buildContractScript(lock_val: int, secret_hash: bytes, pkh_redeem: bytes, pk
|
||||
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):
|
||||
return script[7:39]
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ from sqlalchemy.orm import scoped_session
|
||||
from basicswap.util import (
|
||||
ensure,
|
||||
)
|
||||
from basicswap.interface.base import Curves
|
||||
from basicswap.interface import Curves
|
||||
from basicswap.chainparams import (
|
||||
Coins,
|
||||
)
|
||||
@@ -21,17 +21,13 @@ from basicswap.basicswap_util import (
|
||||
from . import ProtocolInterface
|
||||
from basicswap.contrib.test_framework.script import (
|
||||
CScript, CScriptOp,
|
||||
OP_CHECKMULTISIG
|
||||
)
|
||||
OP_CHECKMULTISIG)
|
||||
|
||||
|
||||
def addLockRefundSigs(self, xmr_swap, ci):
|
||||
self.log.debug('Setting lock refund tx sigs')
|
||||
|
||||
witness_stack = []
|
||||
if ci.coin_type() not in (Coins.DCR, ):
|
||||
witness_stack += [b'', ]
|
||||
witness_stack += [
|
||||
witness_stack = [
|
||||
b'',
|
||||
xmr_swap.al_lock_refund_tx_sig,
|
||||
xmr_swap.af_lock_refund_tx_sig,
|
||||
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)
|
||||
|
||||
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, amount, xmr_offer.b_fee_rate, bid.chain_b_height_start, spend_actual_balance=True, lock_tx_vout=lock_tx_vout)
|
||||
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)
|
||||
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)
|
||||
session.commit()
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2020-2024 tecnovert
|
||||
# Copyright (c) 2020-2023 tecnovert
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
import os
|
||||
import time
|
||||
import json
|
||||
import shlex
|
||||
import urllib
|
||||
import logging
|
||||
import traceback
|
||||
import subprocess
|
||||
from xmlrpc.client import (
|
||||
@@ -18,6 +20,18 @@ from xmlrpc.client import (
|
||||
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():
|
||||
# __getattr__ complicates extending ServerProxy
|
||||
def __init__(self, uri, transport=None, encoding=None, verbose=False,
|
||||
|
||||
@@ -26,5 +26,3 @@ class OpCodes(IntEnum):
|
||||
OP_CHECKSIG = 0xac,
|
||||
OP_CHECKLOCKTIMEVERIFY = 0xb1,
|
||||
OP_CHECKSEQUENCEVERIFY = 0xb2,
|
||||
|
||||
OP_SHA256_DECRED = 0xc0,
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
.error_msg
|
||||
{
|
||||
color:red;
|
||||
}
|
||||
|
||||
#hide {
|
||||
@@ -98,7 +99,7 @@
|
||||
.blurred {
|
||||
filter: blur(4px);
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.error-overlay.non-blurred {
|
||||
@@ -116,13 +117,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* Add this to your existing CSS file */
|
||||
.error {
|
||||
border: 1px solid red !important;
|
||||
}
|
||||
|
||||
.active-container {
|
||||
position: relative;
|
||||
border-radius: 10px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.active-container::before {
|
||||
@@ -137,139 +139,3 @@
|
||||
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 |
@@ -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) {
|
||||
const selectedOption = select.options[select.selectedIndex];
|
||||
const image = selectedOption.getAttribute('data-image');
|
||||
const name = selectedOption.textContent.trim();
|
||||
selectCache[select.id] = { image, name };
|
||||
}
|
||||
|
||||
function updateSelectCache(select) {
|
||||
const selectedOption = select.options[select.selectedIndex];
|
||||
const image = selectedOption.getAttribute('data-image');
|
||||
const name = selectedOption.textContent.trim();
|
||||
selectCache[select.id] = { image, name };
|
||||
}
|
||||
// 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 image = selectedOption.getAttribute('data-image') || '';
|
||||
const name = selectedOption.textContent.trim();
|
||||
select.style.backgroundImage = image ? `url(${image}?${new Date().getTime()})` : '';
|
||||
|
||||
const selectImage = select.nextElementSibling.querySelector('.select-image');
|
||||
if (selectImage) {
|
||||
selectImage.src = image;
|
||||
}
|
||||
|
||||
const selectNameElement = select.nextElementSibling.querySelector('.select-name');
|
||||
if (selectNameElement) {
|
||||
selectNameElement.textContent = name;
|
||||
}
|
||||
function setSelectData(select) {
|
||||
const selectedOption = select.options[select.selectedIndex];
|
||||
const image = selectedOption.getAttribute('data-image') || '/static/images/other/coin.png'; // set a default image URL
|
||||
const name = selectedOption.textContent.trim();
|
||||
if (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);
|
||||
}
|
||||
|
||||
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');
|
||||
// Function to get the selected option data from cache for a given select element
|
||||
function getSelectData(select) {
|
||||
return selectCache[select.id] || {};
|
||||
}
|
||||
|
||||
selectIcons.forEach(icon => icon.style.display = 'none');
|
||||
selectImages.forEach(image => image.style.display = 'none');
|
||||
selectNames.forEach(name => name.style.display = 'none');
|
||||
// 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);
|
||||
}
|
||||
|
||||
function setupCustomSelect(select) {
|
||||
const options = select.querySelectorAll('option');
|
||||
const selectIcon = select.parentElement.querySelector('.select-icon');
|
||||
const selectImage = select.parentElement.querySelector('.select-image');
|
||||
// Add event listener to update select data when an option is selected
|
||||
select.addEventListener('change', () => {
|
||||
setSelectData(select);
|
||||
});
|
||||
});
|
||||
|
||||
options.forEach(option => {
|
||||
const image = option.getAttribute('data-image');
|
||||
if (image) {
|
||||
option.style.backgroundImage = `url(${image})`;
|
||||
}
|
||||
});
|
||||
|
||||
const storedValue = localStorage.getItem(select.name);
|
||||
if (storedValue && select.value == '-1') {
|
||||
select.value = storedValue;
|
||||
}
|
||||
|
||||
select.addEventListener('change', () => {
|
||||
setSelectData(select);
|
||||
localStorage.setItem(select.name, select.value);
|
||||
});
|
||||
|
||||
setSelectData(select);
|
||||
selectIcon.style.display = 'none';
|
||||
selectImage.style.display = 'none';
|
||||
}
|
||||
|
||||
const customSelects = document.querySelectorAll('.custom-select select');
|
||||
customSelects.forEach(setupCustomSelect);
|
||||
});
|
||||
// Hide the select image and name on page load
|
||||
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';
|
||||
});
|
||||
|
||||
60
basicswap/static/js/coin_icons_2.js
Normal file
60
basicswap/static/js/coin_icons_2.js
Normal 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
@@ -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;
|
||||
})();
|
||||
@@ -37,23 +37,4 @@ window.addEventListener('DOMContentLoaded', (event) => {
|
||||
event.target.classList.remove('error');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
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');
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,5 +1,4 @@
|
||||
{% include 'header.html' %}
|
||||
{% from 'style.html' import breadcrumb_line_svg %}
|
||||
<div class="container mx-auto">
|
||||
<section class="p-5 mt-5">
|
||||
<div class="flex flex-wrap items-center -m-2">
|
||||
@@ -10,11 +9,19 @@
|
||||
<p>Home</p>
|
||||
</a>
|
||||
</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>
|
||||
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/404">404</a>
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
@@ -30,6 +37,7 @@
|
||||
<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"><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>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{% include 'header.html' %}
|
||||
{% from 'style.html' import breadcrumb_line_svg, circular_arrows_svg %}
|
||||
<div class="container mx-auto">
|
||||
<section class="p-5 mt-5">
|
||||
<div class="flex flex-wrap items-center -m-2">
|
||||
@@ -10,11 +9,19 @@
|
||||
<p>Home</p>
|
||||
</a>
|
||||
</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>
|
||||
<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>{{ 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>
|
||||
</div>
|
||||
</div>
|
||||
@@ -32,13 +39,23 @@
|
||||
</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">
|
||||
{% 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">
|
||||
{{ circular_arrows_svg | safe }}
|
||||
<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">
|
||||
<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>
|
||||
</a>
|
||||
{% 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">
|
||||
{{ 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>
|
||||
</a>
|
||||
{% endif %}
|
||||
@@ -66,22 +83,22 @@
|
||||
</th>
|
||||
<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>
|
||||
<span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">Offer ID </span>
|
||||
</div>
|
||||
</th>
|
||||
<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>
|
||||
<span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">Bid Status </span>
|
||||
</div>
|
||||
</th>
|
||||
<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>
|
||||
<span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">ITX Status </span>
|
||||
</div>
|
||||
</th>
|
||||
<th class="p-0">
|
||||
<div class="py-3 px-6 rounded-tr-xl bg-coolGray-200 dark:bg-gray-600">
|
||||
<span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">PTX Status</span>
|
||||
<span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">PTX Status </span>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{% 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">
|
||||
<section class="p-5 mt-5">
|
||||
<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="/">
|
||||
<p>Home</p>
|
||||
</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>
|
||||
<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>{{ 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>
|
||||
@@ -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="">
|
||||
<div class="relative z-20 flex flex-wrap items-center -m-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 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">
|
||||
{{ white_automation_svg | safe }}
|
||||
<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">
|
||||
<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>
|
||||
</a>
|
||||
</div>
|
||||
@@ -100,11 +121,30 @@
|
||||
<div class="px-6">
|
||||
<div class="flex flex-wrap justify-end">
|
||||
<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 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">
|
||||
{{ filter_apply_svg | safe }} Apply Filters</button>
|
||||
<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">
|
||||
<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>
|
||||
@@ -164,8 +204,10 @@
|
||||
<div class="flex flex-wrap justify-end">
|
||||
<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">
|
||||
{{ page_back_svg | safe }}
|
||||
<span>Previous</span>
|
||||
<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">
|
||||
<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>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
@@ -175,8 +217,10 @@
|
||||
</div>
|
||||
<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">
|
||||
<span>Next</span>
|
||||
{{ page_forwards_svg | safe }}
|
||||
<span>Page Forwards</span>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{% include 'header.html' %}
|
||||
{% from 'style.html' import breadcrumb_line_svg %}
|
||||
<div class="container mx-auto">
|
||||
<section class="p-5 mt-5">
|
||||
<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="/">
|
||||
<p>Home</p>
|
||||
</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>
|
||||
<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>{{ 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="/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>
|
||||
</ul>
|
||||
</ul>
|
||||
@@ -31,7 +38,7 @@
|
||||
<div class="relative z-20 flex flex-wrap items-center -m-3">
|
||||
<div class="w-full md:w-1/2 p-3">
|
||||
<h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">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>
|
||||
</div>
|
||||
</div>
|
||||
@@ -59,7 +66,7 @@
|
||||
</th>
|
||||
<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">Input</span>
|
||||
<span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">Type</span>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
@@ -107,17 +114,42 @@
|
||||
<div class="flex flex-wrap justify-end">
|
||||
{% if show_edit_form %}
|
||||
<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 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>
|
||||
</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">Edit</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">
|
||||
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ef5844" stroke-linejoin="round">
|
||||
<line x1="16" y1="8" x2="8" y2="16" stroke="#ef5844"></line>
|
||||
<line x1="16" y1="16" x2="8" y2="8" stroke="#ef5844"></line>
|
||||
<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 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>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@@ -1,44 +1,51 @@
|
||||
{% include 'header.html' %}
|
||||
{% from 'style.html' import breadcrumb_line_svg %}
|
||||
<div class="container mx-auto">
|
||||
<section class="p-5 mt-5">
|
||||
<div class="flex flex-wrap items-center -m-2">
|
||||
<div class="w-full md:w-1/2 p-2">
|
||||
<ul class="flex flex-wrap items-center gap-x-3 mb-2">
|
||||
<li>
|
||||
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/">
|
||||
<p>Home</p>
|
||||
</a>
|
||||
<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="/automation">Automation Strategies</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="/automation">New</a>
|
||||
</li>
|
||||
</ul>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="py-4">
|
||||
<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">
|
||||
<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="">
|
||||
<div class="relative z-20 flex flex-wrap items-center -m-3">
|
||||
<div class="w-full md:w-1/2 p-3">
|
||||
<h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">New Automation Strategy</h2>
|
||||
<p class="font-normal text-coolGray-200 dark:text-white"><span class="bold">TODO/WIP:</span>
|
||||
</p>
|
||||
<section class="p-5 mt-5">
|
||||
<div class="flex flex-wrap items-center -m-2">
|
||||
<div class="w-full md:w-1/2 p-2">
|
||||
<ul class="flex flex-wrap items-center gap-x-3 mb-2">
|
||||
<li>
|
||||
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/">
|
||||
<p>Home</p>
|
||||
</a>
|
||||
<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="/automation">Automation Strategies</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="/newautomationstrategy">New</a>
|
||||
</li>
|
||||
</ul>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{% include 'inc_messages.html' %}
|
||||
</section>
|
||||
<section class="py-4">
|
||||
<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">
|
||||
<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="">
|
||||
<div class="relative z-20 flex flex-wrap items-center -m-3">
|
||||
<div class="w-full md:w-1/2 p-3">
|
||||
<h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">New Automation Strategy</h2>
|
||||
<p class="font-normal text-coolGray-200 dark:text-white">Todo <!-- todo -->
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{% include 'inc_messages.html' %}
|
||||
<section>
|
||||
<div class="pl-6 pr-6 pt-0 pb-0 mt-5 h-full overflow-hidden">
|
||||
<div class="pb-6 border-coolGray-100">
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
{% 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">
|
||||
<section class="p-5 mt-5">
|
||||
<div class="flex flex-wrap items-center -m-2">
|
||||
@@ -11,11 +9,19 @@
|
||||
<p>Home</p>
|
||||
</a>
|
||||
</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>
|
||||
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="#">Bids</a>
|
||||
</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>
|
||||
<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>
|
||||
@@ -32,17 +38,23 @@
|
||||
<div class="relative z-20 flex flex-wrap items-center -m-3">
|
||||
<div class="w-full md:w-1/2 p-3">
|
||||
<h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">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 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="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">
|
||||
{{ circular_arrows_svg | safe }}
|
||||
<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">
|
||||
<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>
|
||||
{% 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">
|
||||
{{ circular_arrows_svg | safe }}
|
||||
</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">
|
||||
<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>
|
||||
{% endif %}
|
||||
@@ -82,7 +94,9 @@
|
||||
<td class="py-3 px-6">
|
||||
<div class="content flex py-2">
|
||||
<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>
|
||||
</div>
|
||||
</td>
|
||||
@@ -93,7 +107,9 @@
|
||||
<td class="py-3 px-6">
|
||||
<div class="content flex py-2">
|
||||
<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>
|
||||
</div>
|
||||
</td>
|
||||
@@ -445,7 +461,9 @@
|
||||
<td class="py-3 px-6 bold">Change Bid State:</td>
|
||||
<td class="py-3 px-6">
|
||||
<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">
|
||||
{% for s in data.bid_states %}
|
||||
<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">
|
||||
<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">
|
||||
<option{% if data.debug_ind=="-1" %} selected{% endif %} value="-1">None</option>
|
||||
{% 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>
|
||||
</div>
|
||||
{% 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">
|
||||
<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>
|
||||
@@ -569,4 +589,4 @@
|
||||
</div>
|
||||
{% include 'footer.html' %}
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% 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">
|
||||
<section class="p-5 mt-5">
|
||||
@@ -11,11 +11,19 @@
|
||||
<p>Home</p>
|
||||
</a>
|
||||
</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>
|
||||
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="#">Bids</a>
|
||||
</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>
|
||||
<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>
|
||||
@@ -32,17 +40,25 @@
|
||||
<div class="relative z-20 flex flex-wrap items-center -m-3">
|
||||
<div class="w-full md:w-1/2 p-3">
|
||||
<h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">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 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="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">
|
||||
{{ circular_arrows_svg | safe }}
|
||||
<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">
|
||||
<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>
|
||||
{% 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">
|
||||
{{ circular_arrows_svg | safe }}
|
||||
<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">
|
||||
<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>
|
||||
{% endif %}
|
||||
@@ -82,8 +98,10 @@
|
||||
<td class="py-3 px-6">
|
||||
<div class="content flex py-2">
|
||||
<span class="bold">{{ data.amt_to }} {{ data.ticker_to }}</span>
|
||||
{{ small_arrow_white_right_svg | safe }}
|
||||
<span class="bold">{{ data.amt_from }} {{ data.ticker_from }}</span>
|
||||
<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>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -93,7 +111,9 @@
|
||||
<td class="py-3 px-6">
|
||||
<div class="content flex py-2">
|
||||
<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>
|
||||
</div>
|
||||
</td>
|
||||
@@ -485,8 +505,7 @@
|
||||
<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">
|
||||
<div class="relative">
|
||||
{{ input_arrow_down_svg | safe }}
|
||||
<div class="relative">{{ 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">
|
||||
{% 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>
|
||||
@@ -703,8 +722,7 @@
|
||||
<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">
|
||||
<div class="relative">
|
||||
{{ input_arrow_down_svg | safe }}
|
||||
<div class="relative">{{ 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">
|
||||
{% for s in data.bid_states %}
|
||||
<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">
|
||||
<td class="py-3 px-6 bold">Add Bid Action:</td>
|
||||
<td class="py-3 px-6">
|
||||
<div class="relative">
|
||||
{{ input_arrow_down_svg | safe }}
|
||||
<div class="relative">{{ 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">
|
||||
{% for a in data.bid_actions %}
|
||||
<option value="{{ a[0] }}">{{ a[1] }}</option>
|
||||
@@ -730,8 +747,7 @@
|
||||
<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">
|
||||
<div class="relative">
|
||||
{{ input_arrow_down_svg | safe }}
|
||||
<div class="relative">{{ 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">
|
||||
<option{% if data.debug_ind=="-1" %} selected{% endif %} value="-1">None</option>
|
||||
{% 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>
|
||||
</div>
|
||||
{% 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">
|
||||
<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>
|
||||
@@ -845,4 +861,4 @@
|
||||
</div>
|
||||
{% include 'footer.html' %}
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -1,219 +1,285 @@
|
||||
{% 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">
|
||||
<section class="p-5 mt-5">
|
||||
<div class="flex flex-wrap items-center -m-2">
|
||||
<div class="w-full md:w-1/2 p-2">
|
||||
<ul class="flex flex-wrap items-center gap-x-3 mb-2">
|
||||
<li>
|
||||
<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> {{ 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>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="py-4">
|
||||
<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">
|
||||
<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="">
|
||||
<div class="relative z-20 flex flex-wrap items-center -m-3">
|
||||
<div class="w-full md:w-1/2 p-3">
|
||||
<h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">{{ page_type_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>
|
||||
</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">
|
||||
{% if refresh %}
|
||||
<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">
|
||||
{{ circular_arrows_svg | safe }}
|
||||
<span>Refresh {{ refresh }} seconds</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{% include 'inc_messages.html' %}
|
||||
<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="flex flex-wrap items-center justify-between -m-2">
|
||||
<div class="w-full mx-auto pt-2">
|
||||
<form method="post">
|
||||
<div class="flex items-center justify-center pb-4 dark:text-white">
|
||||
<div class="rounded-b-md">
|
||||
<div class="w-full md:w-0/12">
|
||||
<div class="flex flex-wrap justify-center -m-1.5">
|
||||
<div class="w-full md:w-auto p-1.5">
|
||||
<div class="relative">
|
||||
{{ input_arrow_down_svg | safe }}
|
||||
<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>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full md:w-auto p-1.5">
|
||||
<div class="relative">
|
||||
{{ input_arrow_down_svg | safe }}
|
||||
<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="desc" {% if filters.sort_dir=='desc' %} selected{% endif %}>Descending</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-full md:w-auto p-1.5">
|
||||
<p class="text-sm font-heading bold">State:</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full md:w-auto p-1.5">
|
||||
<div class="relative">
|
||||
{{ input_arrow_down_svg | safe }}
|
||||
<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>
|
||||
{% for s in data.bid_states %}
|
||||
<option value="{{ s[0] }}" {% if filters.bid_state_ind==s[0] %} selected{% endif %}>{{ s[1] }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-full md:w-auto p-1.5">
|
||||
<p class="text-sm font-heading bold">Include Expired:</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full md:w-auto p-1.5">
|
||||
<div class="relative">
|
||||
{{ input_arrow_down_svg | safe }}
|
||||
<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="false" {% if filters.with_expired==false %} selected{% endif %}>Exclude</option>
|
||||
</select> </div>
|
||||
</div>
|
||||
<div class="w-full md:w-auto p-1.5">
|
||||
<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">
|
||||
<span>Clear Filters</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<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">
|
||||
{{ filter_apply_svg | safe }}
|
||||
<span>Apply Filters</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container mt-5 mx-auto">
|
||||
<div class="pt-6 pb-6 bg-coolGray-100 dark:bg-gray-500 rounded-xl">
|
||||
<div class="px-6">
|
||||
<div class="w-full mt-6 pb-6 overflow-x-auto">
|
||||
<table class="w-full min-w-max">
|
||||
<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">Date/Time at</span>
|
||||
</div>
|
||||
</th>
|
||||
<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>
|
||||
</th>
|
||||
<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>
|
||||
</th>
|
||||
<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>
|
||||
</th>
|
||||
<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>
|
||||
</th>
|
||||
<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>
|
||||
</th>
|
||||
<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>
|
||||
</th>
|
||||
<th class="p-0">
|
||||
<div class="py-3 px-6 rounded-tr-xl bg-coolGray-200 dark:bg-gray-600"> <span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">Details</span>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for b in bids %}
|
||||
<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">
|
||||
<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>
|
||||
<div class="pl-3">
|
||||
<div class="font-semibold text-xs dark:text-white">{{ b[0] }}</div>
|
||||
</div>
|
||||
</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"> <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[4] }}</td>
|
||||
<td class="py-3 px-6 text-xs">{{ b[5] }}</td>
|
||||
{% 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> {% 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>
|
||||
{% endif %}
|
||||
</tr>
|
||||
</tbody>
|
||||
{% endfor %}
|
||||
</table> <input type="hidden" name="formid" value="{{ form_id }}"> <input type="hidden" name="pageno" value="{{ filters.page_no }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="rounded-b-md">
|
||||
<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">
|
||||
{% if filters.page_no > 1 %} <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">
|
||||
{{ page_back_svg | safe }}
|
||||
<span>Previous</span>
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="flex items-center">
|
||||
<div class="w-full md:w-auto p-1.5">
|
||||
<p class="text-sm font-heading dark:text-white">Page: {{ filters.page_no }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{% if bids_count > 20 %}
|
||||
<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">
|
||||
<span>Next</span>
|
||||
{{ page_forwards_svg | safe }}
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<section class="p-5 mt-5">
|
||||
<div class="flex flex-wrap items-center -m-2">
|
||||
<div class="w-full md:w-1/2 p-2">
|
||||
<ul class="flex flex-wrap items-center gap-x-3 mb-2">
|
||||
<li>
|
||||
<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>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
<section class="py-4">
|
||||
<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">
|
||||
<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="">
|
||||
<div class="relative z-20 flex flex-wrap items-center -m-3">
|
||||
<div class="w-full md:w-1/2 p-3">
|
||||
<h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">{{ page_type_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>
|
||||
</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"> {% 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">
|
||||
<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>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{% include 'inc_messages.html' %}
|
||||
<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="flex flex-wrap items-center justify-between -m-2">
|
||||
<div class="w-full pt-2">
|
||||
<form method="post">
|
||||
<div class="flex justify-between items-center pb-4 dark:text-white">
|
||||
<div class="rounded-b-md">
|
||||
<div class="w-full md:w-0/12">
|
||||
<div class="flex flex-wrap justify-end -m-1.5">
|
||||
<div class="w-full md:w-auto p-1.5">
|
||||
<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>
|
||||
<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>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full md:w-auto p-1.5">
|
||||
<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>
|
||||
<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="desc" {% if filters.sort_dir=='desc' %} selected{% endif %}>Descending</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-full md:w-auto p-1.5">
|
||||
<p class="text-sm font-heading bold">State:</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full md:w-auto p-1.5">
|
||||
<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>
|
||||
<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>
|
||||
{% for s in data.bid_states %}
|
||||
<option value="{{ s[0] }}" {% if filters.bid_state_ind==s[0] %} selected{% endif %}>{{ s[1] }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-full md:w-auto p-1.5">
|
||||
<p class="text-sm font-heading bold">Include Expired:</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full md:w-auto p-1.5">
|
||||
<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>
|
||||
<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="false" {% if filters.with_expired==false %} selected{% endif %}>Exclude</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full md:w-auto p-1.5">
|
||||
<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 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">
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<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-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>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container mt-5 mx-auto">
|
||||
<div class="pt-6 pb-6 bg-coolGray-100 dark:bg-gray-500 rounded-xl">
|
||||
<div class="px-6">
|
||||
<div class="w-full mt-6 pb-6 overflow-x-auto">
|
||||
<table class="w-full min-w-max">
|
||||
<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">Date/Time at</span>
|
||||
</div>
|
||||
</th>
|
||||
<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>
|
||||
</th>
|
||||
<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>
|
||||
</th>
|
||||
<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>
|
||||
</th>
|
||||
<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>
|
||||
</th>
|
||||
<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>
|
||||
</th>
|
||||
<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>
|
||||
</th>
|
||||
<th class="p-0">
|
||||
<div class="py-3 px-6 rounded-tr-xl bg-coolGray-200 dark:bg-gray-600">
|
||||
<span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">Details</span>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for b in bids %}
|
||||
<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">
|
||||
<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>
|
||||
<div class="pl-3">
|
||||
<div class="font-semibold text-xs dark:text-white">{{ b[0] }}</div>
|
||||
</div>
|
||||
</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">
|
||||
<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[4] }}</td>
|
||||
<td class="py-3 px-6 text-xs">{{ b[5] }}</td>
|
||||
{% 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>
|
||||
{% 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>
|
||||
{% endif %}
|
||||
</tr>
|
||||
</tbody>
|
||||
{% endfor %}
|
||||
</table>
|
||||
<input type="hidden" name="formid" value="{{ form_id }}">
|
||||
<input type="hidden" name="pageno" value="{{ filters.page_no }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="rounded-b-md">
|
||||
<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="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">
|
||||
<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>
|
||||
</svg>
|
||||
<span>Page Back</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-full md:w-auto p-1.5">
|
||||
<p class="text-sm font-heading dark:text-white">Page: {{ filters.page_no }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<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">
|
||||
<span>Page Forwards</span>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
{% include 'footer.html' %}
|
||||
</body>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{% include 'header.html' %}
|
||||
{% from 'style.html' import breadcrumb_line_svg %}
|
||||
<div class="container mx-auto">
|
||||
<section class="p-5 mt-5">
|
||||
<div class="flex flex-wrap items-center -m-2">
|
||||
@@ -10,13 +9,21 @@
|
||||
<p>Home</p>
|
||||
</a>
|
||||
</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>
|
||||
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/wallets">
|
||||
<p>Home</p>
|
||||
</a>
|
||||
</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>
|
||||
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/changepassword">Change Password</a>
|
||||
</li>
|
||||
@@ -144,7 +151,13 @@
|
||||
<div class="px-6">
|
||||
<div class="flex flex-wrap justify-end">
|
||||
<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>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{% include 'header.html' %}
|
||||
{% from 'style.html' import breadcrumb_line_svg, start_process_svg %}
|
||||
<div class="container mx-auto">
|
||||
<section class="p-5 mt-5">
|
||||
<div class="flex flex-wrap items-center -m-2">
|
||||
@@ -10,11 +9,19 @@
|
||||
<p>Home</p>
|
||||
</a>
|
||||
</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>
|
||||
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/debug">Debug</a>
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
@@ -28,7 +35,7 @@
|
||||
<div class="relative z-20 flex flex-wrap items-center -m-3">
|
||||
<div class="w-full md:w-1/2 p-3">
|
||||
<h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">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>
|
||||
@@ -63,15 +70,24 @@
|
||||
<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 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();">
|
||||
Remove Data</button>
|
||||
<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();">
|
||||
Yes - Remove Data</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="opacity-100 text-gray-500 dark:text-gray-100">
|
||||
<td class="py-3 px-6 bold">Reinitialise XMR wallet</td>
|
||||
<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">
|
||||
{{ start_process_svg| safe }} Start Process</button>
|
||||
<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">
|
||||
<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>
|
||||
</tr>
|
||||
<input type="hidden" name="formid" value="{{ form_id }}">
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{% include 'header.html' %}
|
||||
{% from 'style.html' import breadcrumb_line_svg, input_arrow_down_svg %}
|
||||
<div class="container mx-auto">
|
||||
<section class="p-5 mt-5">
|
||||
<div class="flex flex-wrap items-center -m-2">
|
||||
@@ -10,11 +9,19 @@
|
||||
<p>Home</p>
|
||||
</a>
|
||||
</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>
|
||||
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/explores">Explorers</a>
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
@@ -55,7 +62,7 @@
|
||||
</th>
|
||||
<th class="p-0">
|
||||
<div class="py-3 px-6 rounded-tr-xl bg-coolGray-200 dark:bg-gray-600">
|
||||
<span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">Action</span>
|
||||
<span class="text-xs text-gray-600 dark:text-gray-300 font-semibold py-3 px-6">Action</span>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
@@ -63,7 +70,9 @@
|
||||
<tr class="opacity-100 text-gray-500 dark:text-gray-100">
|
||||
<td class="py-3 px-6">
|
||||
<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">
|
||||
<!-- <option value="-1" {% if explorer==-1 %} selected{% endif %}>Select Explorer</option> -->
|
||||
{% for e in explorers %}
|
||||
@@ -73,14 +82,11 @@
|
||||
</div>
|
||||
</td>
|
||||
<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">
|
||||
<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>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="opacity-100 text-gray-500 dark:text-gray-100">
|
||||
@@ -109,7 +115,13 @@
|
||||
<div class="px-6">
|
||||
<div class="flex flex-wrap justify-end">
|
||||
<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>
|
||||
@@ -121,13 +133,13 @@
|
||||
</section>
|
||||
<input type="hidden" name="formid" value="{{ form_id }}">
|
||||
{% if result %}
|
||||
<section class="rounded-xl">
|
||||
<section>
|
||||
<div class="pl-6 pr-6 pt-0 pb-0 h-full overflow-hidden">
|
||||
<div class="border-coolGray-100">
|
||||
<div class="flex flex-wrap items-center justify-between -m-2">
|
||||
<div class="w-full pt-2">
|
||||
<div class="container mt-5 mx-auto">
|
||||
<div class="pt-6 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="w-full mt-6 pb-6 overflow-x-auto">
|
||||
<table class="w-full min-w-max text-sm">
|
||||
@@ -142,37 +154,21 @@
|
||||
</thead>
|
||||
<tr class="opacity-100 text-gray-500 dark:text-gray-100">
|
||||
<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>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</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>
|
||||
{% include 'footer.html' %}
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
<!-- todo round corners -->
|
||||
@@ -1,4 +1,3 @@
|
||||
{% from 'style.html' import love_svg, github_svg %}
|
||||
<section class="overflow-hidden">
|
||||
<div class="container px-4 mx-auto">
|
||||
<div class="flex flex-wrap lg:items-center pt-24 pb-12 -mx-4">
|
||||
@@ -16,7 +15,7 @@
|
||||
<div class="w-full md:w-1/4 px-4"> </div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="border-b border-gray-100 dark:border-gray-500 dark:bg-body dark:border-b-2"></div>
|
||||
<div class="border-b border-gray-100 dark:border-gray-500 dark:bg-body dark:border-b-2"></div>
|
||||
<div class="container px-4 mx-auto">
|
||||
<div class="flex flex-wrap items-center py-12 md:pb-32">
|
||||
<div class="w-full md:w-1/2 mb-6 md:mb-0">
|
||||
@@ -24,17 +23,27 @@
|
||||
<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-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>
|
||||
{{ love_svg | safe }}
|
||||
<span class="ml-2 text-sm font-bold dark:text-white text-gray-90 ">by TV and CRZ</span></div>
|
||||
<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> <span class="ml-2 text-sm font-bold dark:text-white text-gray-90 ">by TV and CRZ</span></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full md:w-1/2">
|
||||
<div class="flex flex-wrap md:justify-end -mx-5">
|
||||
<div class="px-5">
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
@@ -42,6 +51,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
var toggleImages = function() {
|
||||
@@ -77,6 +87,9 @@
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
var themeToggleDarkIcon = document.getElementById('theme-toggle-dark-icon');
|
||||
var themeToggleLightIcon = document.getElementById('theme-toggle-light-icon');
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<!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">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
@@ -92,34 +91,57 @@
|
||||
<body class="dark:bg-gray-700">
|
||||
<section>
|
||||
<nav class="relative bg-gray-700">
|
||||
|
||||
<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>
|
||||
<ul class="hidden xl:flex">
|
||||
<li>
|
||||
<a class="flex mr-10 items-center py-3 text-gray-50 hover:text-gray-100 text-sm" href="/wallets">
|
||||
{{ wallet_svg | safe }}
|
||||
<span>Wallets</span>
|
||||
</a>
|
||||
<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> <span>Wallets</span></a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<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>
|
||||
<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>
|
||||
<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> <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>
|
||||
<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">
|
||||
{{ new_offer_svg | safe }}
|
||||
<span>Place new Offer</span>
|
||||
</a>
|
||||
<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">
|
||||
<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> <span>Place new Offer</span></a>
|
||||
</li>
|
||||
</ul>
|
||||
<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">
|
||||
{{ settings_svg | safe }} Settings & Tools
|
||||
{{ header_arrow_down_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">
|
||||
<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>
|
||||
</ul>
|
||||
<!-- dropdown settings & tools -->
|
||||
@@ -127,77 +149,138 @@
|
||||
<ul class="py-0 text-sm text-gray-700" aria-labelledby="dropdownLargeButton">
|
||||
<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>
|
||||
{{ 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>
|
||||
{% if debug_mode == true %}
|
||||
<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>
|
||||
{{ 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>
|
||||
{% endif %}
|
||||
{% if debug_mode == true %}
|
||||
<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>
|
||||
{{ debug_svg | safe }} Debug</a>
|
||||
<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>
|
||||
<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>
|
||||
{% endif %}
|
||||
{% if debug_mode == true %}
|
||||
<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>
|
||||
{{ 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>
|
||||
{% endif %}
|
||||
{% if use_tor_proxy == true %}
|
||||
<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>
|
||||
{{ tor_svg | safe }} Tor </a>
|
||||
<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>
|
||||
<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>
|
||||
{% endif %}
|
||||
<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>
|
||||
{{ 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>
|
||||
<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
|
||||
<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>
|
||||
<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>
|
||||
<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> 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>
|
||||
{% if debug_mode == true %}
|
||||
<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>
|
||||
{{ 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>
|
||||
{% endif %}
|
||||
</ul>
|
||||
<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>
|
||||
{{ 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>
|
||||
|
||||
<!-- dropdown settings & tools -->
|
||||
|
||||
<!-- 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">
|
||||
{{ 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">
|
||||
<!-- 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> -->
|
||||
<!-- Red <div class="inline-flex relative -top-2 right-3 w-3 h-3 bg-red-500 rounded-full border-2 border-white"></div> -->
|
||||
<!-- Todo -->
|
||||
</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>
|
||||
</button>
|
||||
|
||||
<!-- 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 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">
|
||||
{% 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="inline-flex flex-shrink-0 justify-center items-center w-8 h-8 bg-blue-500 rounded-lg">
|
||||
{{ notifications_network_offer_svg | safe }}
|
||||
</div>
|
||||
<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>
|
||||
<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">
|
||||
NEW NETWORK <a class="underline text-blue-500" href="/offer/{{ entry[2].offer_id }}">OFFER</a></span>
|
||||
@@ -209,9 +292,7 @@
|
||||
</div>
|
||||
{% elif entry[1] == 2 %}
|
||||
<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">
|
||||
{{ notifications_new_bid_on_offer_svg | safe }}
|
||||
</div>
|
||||
<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>
|
||||
<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">
|
||||
<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>
|
||||
{% elif entry[1] == 3 %}
|
||||
<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">
|
||||
{{ notifications_bid_accepted_svg | safe }}
|
||||
</div>
|
||||
<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>
|
||||
<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">
|
||||
<a class="underline text-blue-500" href="/bid/{{ entry[2].bid_id }}">BID</a> ACCEPTED</span>
|
||||
@@ -237,9 +316,7 @@
|
||||
</div>
|
||||
{% else %}
|
||||
<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">
|
||||
{{ notifications_unknow_event_svg | safe }}
|
||||
</div>
|
||||
<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>
|
||||
<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">
|
||||
UNKNOWN EVENT</span>
|
||||
@@ -251,19 +328,36 @@
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</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>
|
||||
<!-- 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-shrink-0 w-px h-10 bg-gray-400 dark:bg-gray-400 ml-4 mr-5"></div>
|
||||
{% if debug_mode == true %}
|
||||
<!-- dev mode icons on/off -->
|
||||
<ul class="xl:flex">
|
||||
<li>
|
||||
<div data-tooltip-target="tooltip-debug" class="ml-5 flex items-center text-gray-50 hover:text-gray-100 text-sm">
|
||||
{{ debug_nerd_svg | safe }}
|
||||
<div data-tooltip-target="tooltip-DEV" class="ml-5 flex items-center text-gray-50 hover:text-gray-100 text-sm">
|
||||
<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>
|
||||
<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>
|
||||
{% if debug_ui_mode == true %}
|
||||
<p><b>Debug UI mode:</b> Active</p>
|
||||
@@ -278,7 +372,7 @@
|
||||
<ul class="xl:flex"><li>
|
||||
{% 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">
|
||||
{{ 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>
|
||||
<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>
|
||||
@@ -286,7 +380,7 @@
|
||||
{% else %}
|
||||
<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">
|
||||
{{ 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>
|
||||
<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">
|
||||
@@ -301,60 +395,68 @@
|
||||
<ul class="xl:flex ml-5">
|
||||
<li>
|
||||
<a href="/tor">
|
||||
<div data-tooltip-target="tooltip-tor" class="flex items-center text-gray-50 hover:text-gray-100 text-sm">
|
||||
{{ tor_purple_svg | safe }}
|
||||
</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>
|
||||
<div data-tooltip-target="tooltip-TOR" class="flex items-center text-gray-50 hover:text-gray-100 text-sm">
|
||||
<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>
|
||||
</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>
|
||||
</ul>
|
||||
<!-- tor -->
|
||||
{% 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">
|
||||
{{ sun_svg | safe }}
|
||||
{{ moon_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>
|
||||
<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>
|
||||
<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>
|
||||
</div>
|
||||
|
||||
<div class="hidden xl:block"></div>
|
||||
|
||||
<!-- mobile menu -->
|
||||
<div class="ml-auto flex xl:hidden">
|
||||
<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>
|
||||
</div>
|
||||
|
||||
<!-- mobile menu -->
|
||||
</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="flex items-center container flex flex-wrap items-center justify-between items-center mx-auto">
|
||||
<ul class="flex items-center">
|
||||
|
||||
<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">
|
||||
<div id="swapContainer" class="inline-flex center-spin ml-7 mr-2" {% if summary.num_swapping != 0 %}style="animation: spin 2s linear infinite;"{% endif %}>
|
||||
{% if summary.num_swapping != 0 %}
|
||||
{{ swap_in_progress_green_svg | safe }}
|
||||
{% else %}
|
||||
{{ swap_in_progress_svg | safe }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<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 num-swap">{{ summary.num_swapping }}</span>
|
||||
</a>
|
||||
<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><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>
|
||||
|
||||
<div class="flex-shrink-0 w-px h-10 bg-gray-200 dark:bg-gray-400 mr-10"></div>
|
||||
|
||||
<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">
|
||||
{{ your_offers_svg | safe }}
|
||||
<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>
|
||||
<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>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">
|
||||
<p><b>Total:</b> {{ summary.num_sent_offers }}</p>
|
||||
@@ -364,13 +466,23 @@
|
||||
</li>
|
||||
<div class="flex-shrink-0 w-px h-10 bg-gray-200 dark:bg-gray-400 mr-10"></div>
|
||||
<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 }}
|
||||
<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>
|
||||
<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">
|
||||
<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>
|
||||
<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 }}
|
||||
<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>
|
||||
<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>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>
|
||||
|
||||
<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>
|
||||
<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">
|
||||
{{ bids_sent_svg| safe }}
|
||||
<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>
|
||||
<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>Bids Sent</span><span class="inline-flex justify-center items-center text-xs font-semibold ml-3 mr-2 px-2.5 py-1 font-small text-white bg-blue-500 rounded-full">{{ summary.num_sent_active_bids }}</span></a>
|
||||
<div id="tooltip-bids-sent" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
|
||||
<p><b>Total:</b> {{ summary.num_sent_bids }}</p>
|
||||
<div class="tooltip-arrow" data-popper-arrow></div>
|
||||
@@ -403,46 +520,103 @@
|
||||
<ul class="mb-8 text-sm font-medium">
|
||||
<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">
|
||||
{{ wallet_svg | safe }}
|
||||
</span><span>Wallets</span>
|
||||
<span class="inline-block ml-auto"></span></a>
|
||||
<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>
|
||||
</span><span>Wallets</span> <span class="inline-block ml-auto">
|
||||
</span></a>
|
||||
</li>
|
||||
</ul>
|
||||
<h3 class="mb-2 text-xs uppercase text-gray-300 font-medium dark:text-gray-300">Exchange</h3>
|
||||
<ul class="text-sm font-medium">
|
||||
<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">
|
||||
{{ 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>
|
||||
</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">
|
||||
{{ swap_in_progress_mobile_svg | safe }}
|
||||
</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>
|
||||
<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>
|
||||
</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">
|
||||
{{ 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>
|
||||
</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">
|
||||
{{ 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>
|
||||
</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">
|
||||
{{ 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>
|
||||
</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">
|
||||
{{ 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>
|
||||
</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">
|
||||
{{ 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>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -450,65 +624,127 @@
|
||||
<ul class="text-sm font-medium">
|
||||
<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">
|
||||
{{ 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>
|
||||
</li>
|
||||
{% if debug_mode == true %}
|
||||
<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">
|
||||
{{ 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>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if debug_mode == true %}
|
||||
<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">
|
||||
{{ 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>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if debug_mode == true %}
|
||||
<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">
|
||||
{{ 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>
|
||||
</li>
|
||||
{% endif %}
|
||||
<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">
|
||||
{{ 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>
|
||||
</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">
|
||||
{{ 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>
|
||||
</li>
|
||||
{% if debug_mode == true %}
|
||||
<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">
|
||||
{{ 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>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if use_tor_proxy == true %}
|
||||
<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">
|
||||
{{ 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>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
<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">
|
||||
{{ 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>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
<!-- mobile sidebar -->
|
||||
|
||||
<!-- mobile sidebar -->
|
||||
</section>
|
||||
{% if ws_url %}
|
||||
<script>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{% include 'header.html' %}
|
||||
{% from 'style.html' import breadcrumb_line_svg, red_cross_close_svg %}
|
||||
<div class="container mx-auto">
|
||||
<section class="p-5 mt-5">
|
||||
<div class="flex flex-wrap items-center -m-2">
|
||||
@@ -10,13 +9,21 @@
|
||||
<p>Home</p>
|
||||
</a>
|
||||
</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>
|
||||
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/smsgaddresses">Identity</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="/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>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -31,7 +38,7 @@
|
||||
<div class="relative z-20 flex flex-wrap items-center -m-3">
|
||||
<div class="w-full md:w-1/2 p-3">
|
||||
<h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">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>
|
||||
@@ -146,14 +153,34 @@
|
||||
<div class="flex flex-wrap justify-end">
|
||||
{% if data.show_edit_form %}
|
||||
<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 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>
|
||||
{% 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">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>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
@@ -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 %}
|
||||
<section class="py-4" id="messages_{{ m[0] }}" role="alert">
|
||||
<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-1 p-2">
|
||||
<div class="flex flex-wrap -m-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>
|
||||
|
||||
|
||||
<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 class="flex-1 p-1">
|
||||
<h3 class="infomsg font-medium text-sm text-green-900">{{ m[1] }}</h3></div>
|
||||
</div>
|
||||
</div>
|
||||
<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>
|
||||
{{ green_cross_close_svg | safe }}
|
||||
<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>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
@@ -32,27 +29,27 @@
|
||||
{% if err_messages %}
|
||||
<section class="py-4" id="err_messages_{{ err_messages[0][0] }}" role="alert">
|
||||
<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-1 p-2">
|
||||
<div class="flex flex-wrap -m-1">
|
||||
<div class="w-auto p-1">
|
||||
{{ circular_error_messages_svg | safe }}
|
||||
{% for m in err_messages %}
|
||||
<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 %}
|
||||
</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 %}
|
||||
<li class="font-medium text-sm text-red-500 error_msg">{{ m[1] }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<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>
|
||||
{{ 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>
|
||||
</div>
|
||||
</div>
|
||||
@@ -60,3 +57,4 @@
|
||||
</div>
|
||||
</section>
|
||||
{% endif %}
|
||||
<!-- todo messages colors better for darkmode -->
|
||||
|
||||
@@ -1,17 +1,23 @@
|
||||
{% include 'header.html' %}
|
||||
{% from 'style.html' import index_wallet_svg, index_trading_svg, index_support_svg %}
|
||||
<div class="container mx-auto">
|
||||
<section class="relative py-24 overflow-hidden">
|
||||
<div class="container px-4 mx-auto mb-16 md:mb-0">
|
||||
<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>
|
||||
<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="w-full md:w-auto mb-6 md:mb-0 md:pr-6">
|
||||
<a href="/wallets">
|
||||
<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 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">
|
||||
<a href="/offers">
|
||||
<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 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">
|
||||
<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">
|
||||
{{ 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 class="w-full md:flex-1 md:pt-3">
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
{% 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">
|
||||
<section class="p-5 mt-5">
|
||||
<div class="flex flex-wrap items-center -m-2">
|
||||
@@ -12,13 +10,17 @@
|
||||
</a>
|
||||
</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>
|
||||
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="#">Offer</a>
|
||||
</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>
|
||||
<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="">
|
||||
<div class="relative z-20 flex flex-wrap items-center -m-3">
|
||||
<div class="w-full md:w-1/2 p-3">
|
||||
<h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">Offer</h2>
|
||||
<p class="font-normal text-coolGray-200 dark:text-white"><span class="bold">OFFER ID:</span> {{ offer_id }}</p>
|
||||
<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">Offer ID: {{ offer_id }}</p>
|
||||
</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">
|
||||
{% 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">
|
||||
{{ circular_arrows_svg | safe }}<span>Refresh {{ refresh }} seconds</span>
|
||||
<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">
|
||||
<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>
|
||||
{% 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">
|
||||
{{ circular_arrows_svg | safe }}<span>Refresh</span>
|
||||
<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">
|
||||
<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>
|
||||
{% endif %}
|
||||
</div>
|
||||
@@ -55,30 +69,37 @@
|
||||
</section>
|
||||
{% include 'inc_messages.html' %}
|
||||
{% 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="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-1 p-2">
|
||||
<div class="flex flex-wrap -m-1">
|
||||
<div class="w-auto p-1">
|
||||
{{ confirm_green_svg | safe }}
|
||||
</div>
|
||||
<div class="flex-1 p-1">
|
||||
<h3 class="infomsg font-medium text-sm text-green-900">Sent Bid {{ sent_bid_id }}</h3></div>
|
||||
</div>
|
||||
</div>
|
||||
<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>
|
||||
{{ green_cross_close_svg | safe }}
|
||||
</button>
|
||||
</div>
|
||||
<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-1 p-2">
|
||||
<div class="flex flex-wrap -m-1">
|
||||
<div class="w-auto p-1">
|
||||
<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 class="flex-1 p-1">
|
||||
<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 class="w-auto p-2">
|
||||
<a href="#">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<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>
|
||||
</section>
|
||||
{% endif %}
|
||||
<section>
|
||||
</section>
|
||||
{% endif %}
|
||||
<section>
|
||||
<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="flex flex-wrap items-center justify-between -m-2">
|
||||
@@ -234,7 +255,7 @@
|
||||
</tr>
|
||||
<tr class="opacity-100 text-gray-500 dark:text-gray-100 hover:bg-coolGray-200 dark:hover:bg-gray-600">
|
||||
<td class="py-3 px-6 bold">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>
|
||||
{% endif %}
|
||||
</table>
|
||||
@@ -339,7 +360,9 @@
|
||||
<td class="pr-3 px-6 bold">Auto Accept Strategy:</td>
|
||||
<td class="py-3 px-6">
|
||||
<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">
|
||||
<option value="-1" {% if data.automation_strat_id==-1 %} selected{% endif %}>None</option>
|
||||
{% for a in data.automation_strategies %}
|
||||
@@ -397,10 +420,8 @@
|
||||
</thead>
|
||||
<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 }}
|
||||
{% if data.xmr_type == true %}
|
||||
(excluding estimated {{ data.amt_from_lock_spend_tx_fee }} {{ data.tla_from }} in tx fees).
|
||||
{% else %}
|
||||
(excluding a tx fee).
|
||||
{% if data.xmr_type == true %} (excluding estimated {{ data.amt_from_lock_spend_tx_fee }} {{ data.tla_from }} in tx fees).
|
||||
{% else %} (excluding a tx fee).
|
||||
{% 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>
|
||||
@@ -410,7 +431,9 @@
|
||||
<td class="py-3 px-6">
|
||||
<div class="w-full md:flex-1">
|
||||
<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">
|
||||
{% for a in addrs %}
|
||||
<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">
|
||||
<div class="w-full md:flex-1">
|
||||
<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">
|
||||
<option{% if data.debug_ind=="-1" %} selected{% endif %} value="-1">None</option>
|
||||
{% for a in data.debug_options %}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,4 @@
|
||||
{% include 'header.html' %}
|
||||
{% from 'style.html' import breadcrumb_line_svg, input_arrow_down_svg %}
|
||||
<div class="container mx-auto">
|
||||
<section class="p-5 mt-5">
|
||||
<div class="flex flex-wrap items-center -m-2">
|
||||
@@ -10,11 +9,19 @@
|
||||
<p>Home</p>
|
||||
</a>
|
||||
</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>
|
||||
<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> {{ 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>
|
||||
</div>
|
||||
</div>
|
||||
@@ -28,6 +35,7 @@
|
||||
<div class="relative z-20 flex flex-wrap items-center -m-3">
|
||||
<div class="w-full md:w-1/2 p-3">
|
||||
<h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">RPC Console</h2>
|
||||
<p class="font-normal text-coolGray-200 dark:text-white">Manage your BasicSwap client and coins settings.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -62,8 +70,10 @@
|
||||
<tr class="opacity-100 text-gray-500 dark:text-gray-100">
|
||||
<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="coin_type" id="coin_type" onchange="set_coin();">
|
||||
<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="coin_type">
|
||||
<option value="-1" {% if coin_type==-1 %} selected{% endif %}>Select Coin</option>
|
||||
{% for c in coins %}
|
||||
<option value="{{ c[0] }}" {% if coin_type==c[0] %} selected{% endif %}>{{ c[1] }}</option>
|
||||
@@ -72,21 +82,23 @@
|
||||
</div>
|
||||
</td>
|
||||
<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>
|
||||
</tr>
|
||||
<tr class="opacity-100 text-gray-500 dark:text-gray-100">
|
||||
<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="call_type" id="call_type" >
|
||||
<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="call_type">
|
||||
<option value="cli" {% if call_type=="cli" %} selected{% endif %}>CLI</option>
|
||||
<option value="http" {% if call_type=="http" %} selected{% endif %}>HTTP</option>
|
||||
</select>
|
||||
</div>
|
||||
</td>
|
||||
<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>
|
||||
</table>
|
||||
</div>
|
||||
@@ -109,7 +121,13 @@
|
||||
<div class="px-6">
|
||||
<div class="flex flex-wrap justify-end">
|
||||
<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>
|
||||
@@ -120,15 +138,14 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{% if result %}
|
||||
<section class="rounded-xl">
|
||||
<section>
|
||||
<div class="pl-6 pr-6 pt-0 pb-0 h-full overflow-hidden">
|
||||
<div class="border-coolGray-100">
|
||||
<div class="flex flex-wrap items-center justify-between -m-2">
|
||||
<div class="w-full pt-2">
|
||||
<div class="container mt-5 mx-auto">
|
||||
<div class="pt-6 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="w-full mt-6 pb-6 overflow-x-auto">
|
||||
<table class="w-full min-w-max text-sm">
|
||||
@@ -136,7 +153,7 @@
|
||||
<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">RPC Console Output:</span>
|
||||
<span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">RPC Console Output</span>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
@@ -149,55 +166,14 @@
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</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>
|
||||
{% include 'footer.html' %}
|
||||
</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>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{% include 'header.html' %}
|
||||
{% from 'style.html' import breadcrumb_line_svg, input_arrow_down_svg %}
|
||||
<div class="container mx-auto">
|
||||
<section class="p-5 mt-5">
|
||||
<div class="flex flex-wrap items-center -m-2">
|
||||
@@ -10,11 +9,17 @@
|
||||
<p>Home</p>
|
||||
</a>
|
||||
</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>
|
||||
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/settings">Settings</a>
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
@@ -40,16 +45,16 @@
|
||||
<div class="pb-6">
|
||||
<div class="flex flex-wrap items-center justify-between -m-2">
|
||||
<div class="w-full pt-2">
|
||||
<div class="mb-4 border-b pb-5 border-gray-200 dark:border-gray-500">
|
||||
<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">
|
||||
<li class="mr-2">
|
||||
<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>
|
||||
<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 -mb-px" id="myTab" data-tabs-toggle="#settingstab" role="tablist">
|
||||
<li class="mr-2" role="presentation">
|
||||
<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 class="mr-2">
|
||||
<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>
|
||||
<li class="mr-2" role="presentation">
|
||||
<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 class="mr-2">
|
||||
<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>
|
||||
<li class="mr-2" role="presentation">
|
||||
<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>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -110,7 +115,9 @@
|
||||
<td class="py-3 px-6 bold">Manage Daemon</td>
|
||||
<td class="py-3 px-6">
|
||||
<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 }}">
|
||||
<option value="true" {% if c.manage_daemon==true %} selected{% endif %}>True</option>
|
||||
<option value="false" {% if c.manage_daemon==false %} selected{% endif %}>False</option>
|
||||
@@ -141,7 +148,9 @@
|
||||
<td class="py-3 px-6">
|
||||
<div class="w-52 md:flex-1">
|
||||
<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 }}">
|
||||
<option value="true" {% if c.autosetdaemon==true %} selected{% endif %}>True</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">
|
||||
<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 }}">
|
||||
<option value="local" {% if c.lookups=='local' %} selected{% endif %}>Local Node</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">
|
||||
<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 }}">
|
||||
<option value="0" {% if c.fee_priority==0 %} selected{% endif %}>Auto</option>
|
||||
<option value="1" {% if c.fee_priority==1 %} selected{% endif %}>Slow</option>
|
||||
<option value="2" {% if c.fee_priority==2 %} selected{% endif %}>Normal</option>
|
||||
<option value="3" {% if c.fee_priority==3 %} selected{% endif %}>Fast</option>
|
||||
<option value="0" {% if c.fee_priority==0 %} selected{% endif %}>Default</option>
|
||||
<option value="1" {% if c.fee_priority==1 %} selected{% endif %}>Low</option>
|
||||
<option value="2" {% if c.fee_priority==2 %} selected{% endif %}>Medium</option>
|
||||
<option value="3" {% if c.fee_priority==3 %} selected{% endif %}>High</option>
|
||||
</select>
|
||||
</div>
|
||||
</td>
|
||||
@@ -285,7 +298,9 @@
|
||||
<td class="py-3 px-6 bold w-96 bold">Debug Mode</td>
|
||||
<td class="py-3 px-6">
|
||||
<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">
|
||||
<option {% if general_settings.debug %}selected{% endif %} value="true">True</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">
|
||||
<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">
|
||||
<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>
|
||||
@@ -309,7 +326,9 @@
|
||||
<td class="py-3 px-6 bold">Remove DB records for expired offers</td>
|
||||
<td class="py-3 px-6">
|
||||
<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">
|
||||
<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>
|
||||
@@ -386,7 +405,9 @@
|
||||
<td class="py-3 px-6 bold w-96 bold">Show Price Chart</td>
|
||||
<td class="py-3 px-6">
|
||||
<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">
|
||||
<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>
|
||||
@@ -395,32 +416,14 @@
|
||||
</td>
|
||||
</tr>
|
||||
<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">
|
||||
<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 />
|
||||
</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>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@@ -493,7 +496,9 @@
|
||||
<td class="py-3 px-6">
|
||||
<div class="w-1/5 md:flex-1">
|
||||
<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">
|
||||
<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>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{% 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">
|
||||
<section class="p-5 mt-5">
|
||||
<div class="flex flex-wrap items-center -m-2">
|
||||
@@ -10,11 +9,19 @@
|
||||
<p>Home</p>
|
||||
</a>
|
||||
</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>
|
||||
<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>{{ 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>
|
||||
</div>
|
||||
</div>
|
||||
@@ -36,13 +43,13 @@
|
||||
</section>
|
||||
{% include 'inc_messages.html' %}
|
||||
<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" value="{{ data.addr_data.addr }}">
|
||||
<section class="p-6 bg-body dark:bg-gray-700">
|
||||
<div class="flex flex-wrap items-center">
|
||||
<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>
|
||||
</section>
|
||||
@@ -78,7 +85,9 @@
|
||||
<td class="py-3 px-6">Active</td>
|
||||
<td class="py-3 px-6">
|
||||
<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">
|
||||
<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>
|
||||
@@ -112,10 +121,24 @@
|
||||
<div class="px-6">
|
||||
<div class="flex flex-wrap justify-end">
|
||||
<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 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>
|
||||
@@ -184,10 +207,24 @@
|
||||
<div class="px-6">
|
||||
<div class="flex flex-wrap justify-end">
|
||||
<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 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>
|
||||
@@ -262,10 +299,24 @@
|
||||
<div class="px-6">
|
||||
<div class="flex flex-wrap justify-end">
|
||||
<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 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>
|
||||
@@ -309,21 +360,15 @@
|
||||
<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">
|
||||
<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">
|
||||
<option value="created_at" {% if filters.sort_by=='created_at' %} selected{% endif %}>Created At</option>
|
||||
</select>
|
||||
</div>
|
||||
</td>
|
||||
<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">
|
||||
<option value="asc" {% if filters.sort_dir=='asc' %} selected{% endif %}>Ascending</option>
|
||||
<option value="desc" {% if filters.sort_dir=='desc' %} selected{% endif %}>Descending</option>
|
||||
</select>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<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">
|
||||
<td class="py-3 px-6">Type</td>
|
||||
<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">
|
||||
<option{% if filters.addr_type=="-1" %} selected{% endif %} value="-1">Any</option>
|
||||
{% for a in page_data.addr_types %}
|
||||
<option{% if filters.addr_type==a[0] %} selected{% endif %} value="{{ a[0] }}">{{ a[1] }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</td>
|
||||
<td class="py-4 pr-5"></td>
|
||||
</tr>
|
||||
@@ -365,22 +407,50 @@
|
||||
<div class="px-6">
|
||||
<div class="flex flex-wrap justify-end">
|
||||
<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 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">
|
||||
{{ 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 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">
|
||||
{{ circle_plus_svg | safe }}
|
||||
New Address</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">
|
||||
<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 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">
|
||||
{{ circle_plus_svg | safe }}
|
||||
Add Sending Address</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">
|
||||
<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>
|
||||
@@ -480,8 +550,10 @@
|
||||
<div class="flex flex-wrap justify-end">
|
||||
<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">
|
||||
{{ page_back_svg| safe }}
|
||||
<span>Previous</span>
|
||||
<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">
|
||||
<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>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
@@ -491,8 +563,10 @@
|
||||
</div>
|
||||
<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">
|
||||
<span>Next</span>
|
||||
{{ page_forwards_svg| safe }}
|
||||
<span>Page Forwards</span>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,697 +1,118 @@
|
||||
{% 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">
|
||||
<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 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">
|
||||
<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 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>
|
||||
</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">
|
||||
<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 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">
|
||||
<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 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 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>
|
||||
' %}
|
||||
{% 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">
|
||||
<rect x="2" y="9" width="12" height="14"></rect>
|
||||
<polyline points=" 6,5 18,5 18,19 " stroke="#ffffff"></polyline>
|
||||
<polyline points=" 10,1 22,1 22,15 " stroke="#ffffff"></polyline>
|
||||
</g>
|
||||
</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">
|
||||
<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>
|
||||
<line x1="12" y1="3" x2="12" y2="13" stroke="#ffffff"></line>
|
||||
<line x1="17" y1="8" x2="7" y2="8" stroke="#ffffff"></line>
|
||||
</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>
|
||||
' %}
|
||||
{% 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="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>
|
||||
</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">
|
||||
<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 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>
|
||||
</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>
|
||||
</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">
|
||||
<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>
|
||||
' %}
|
||||
{% 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">
|
||||
<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>
|
||||
' %}
|
||||
{% 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>
|
||||
</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>
|
||||
</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_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">
|
||||
<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 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">
|
||||
<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 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>
|
||||
</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">
|
||||
<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 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">
|
||||
<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 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 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>' %}
|
||||
|
||||
{% 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">
|
||||
<rect x="2" y="9" width="12" height="14"></rect>
|
||||
<polyline points=" 6,5 18,5 18,19 " stroke="#ffffff"></polyline>
|
||||
<polyline points=" 10,1 22,1 22,15 " stroke="#ffffff"></polyline>
|
||||
</g>
|
||||
</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">
|
||||
<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>
|
||||
<line x1="12" y1="3" x2="12" y2="13" stroke="#ffffff"></line>
|
||||
<line x1="17" y1="8" x2="7" y2="8" stroke="#ffffff"></line>
|
||||
</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>
|
||||
' %}
|
||||
|
||||
{% 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="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>
|
||||
</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">
|
||||
<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 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>
|
||||
</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>
|
||||
</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">
|
||||
<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>
|
||||
' %}
|
||||
|
||||
{% 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">
|
||||
<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>
|
||||
' %}
|
||||
|
||||
|
||||
{% 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>
|
||||
</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>
|
||||
</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' %}
|
||||
@@ -1,5 +1,4 @@
|
||||
{% include 'header.html' %}
|
||||
{% from 'style.html' import breadcrumb_line_svg, circular_arrows_svg %}
|
||||
<div class="container mx-auto">
|
||||
<section class="p-5 mt-5">
|
||||
<div class="flex flex-wrap items-center -m-2">
|
||||
@@ -10,11 +9,19 @@
|
||||
<p>Home</p>
|
||||
</a>
|
||||
</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>
|
||||
<a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/tor">Tor</a>
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
@@ -32,13 +39,23 @@
|
||||
</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">
|
||||
{% 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">
|
||||
{{ circular_arrows_svg | safe }}
|
||||
<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">
|
||||
<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>
|
||||
{% 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">
|
||||
{{ circular_arrows_svg | safe }}
|
||||
<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">
|
||||
<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>
|
||||
{% endif %}
|
||||
|
||||
@@ -103,8 +103,8 @@
|
||||
<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 class="text-center">
|
||||
<span class="text-xs font-medium text-coolGray-500 dark:text-gray-500" contenteditable="false">{{ title }} - GUI 3.0.0</span>
|
||||
</p>
|
||||
<span class="text-xs font-medium text-coolGray-500 dark:text-gray-500" contenteditable="false">{{ title }} - GUI 2.0.2</span>
|
||||
</p>
|
||||
<input type="hidden" name="formid" value="{{ form_id }}">
|
||||
</form>
|
||||
</div>
|
||||
@@ -187,4 +187,4 @@ passwordToggle.addEventListener('change', function() {
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -53,7 +53,7 @@
|
||||
{% if w.error %}<p>Error: {{ w.error }}</p>
|
||||
{% else %}
|
||||
<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">
|
||||
<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 }}">
|
||||
@@ -68,14 +68,14 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="p-6 bg-coolGray-100 dark:bg-gray-600">
|
||||
<div class="flex mb-2 justify-between items-center">
|
||||
<h4 class="text-xs font-medium dark:text-white">Balance:</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 coinname-value" data-coinname="{{ w.name }}">{{ w.balance }} {{ w.ticker }}</div>
|
||||
</div>
|
||||
<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>
|
||||
<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>
|
||||
<div class="flex mb-2 justify-between items-center">
|
||||
<h4 class="text-xs font-medium dark:text-white">Balance:</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 coinname-value" data-coinname="{{ w.name }}">{{ w.balance }} {{ w.ticker }}</div>
|
||||
</div>
|
||||
<div class="flex mb-2 justify-between items-center">
|
||||
<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"></div>
|
||||
</div>
|
||||
{% if w.pending %}
|
||||
<div class="flex mb-2 justify-between items-center">
|
||||
<h4 class="text-xs font-bold text-green-500 dark:text-green-500">Pending:</h4>
|
||||
@@ -116,7 +116,7 @@
|
||||
{% if w.anon_pending %}
|
||||
<div class="flex mb-2 justify-between items-center">
|
||||
<h4 class="text-xs font-bold text-green-500 dark:text-green-500">Anon Pending:</h4>
|
||||
<span class="bold inline-block py-1 px-2 rounded-full bg-green-100 text-xs text-green-500 dark:bg-gray-500 dark:text-green-500 coinname-value" data-coinname="{{ w.name }}">
|
||||
<span class="bold inline-block py-1 px-2 rounded-full bg-green-100 text-xs text-green-500 dark:bg-gray-500 dark:text-green-500 coinname-value" data-coinname="{{ w.name }}">
|
||||
+{{ w.anon_pending }} {{ w.ticker }}</span>
|
||||
</div>
|
||||
<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">{{ w.synced }}%</span>
|
||||
</div>
|
||||
<div class="w-full bg-gray-200 rounded-full h-1 " data-tooltip-target="tooltip-blocks{{loop.index}}">
|
||||
<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>
|
||||
<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 class="w-full bg-gray-200 rounded-full h-1">
|
||||
<div class="bg-blue-500 h-1 rounded-full" style="width: {{ w.synced }}%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -216,10 +203,7 @@ const coinNameToSymbol = {
|
||||
'Litecoin': 'LTC',
|
||||
'Firo': 'FIRO',
|
||||
'Dash': 'DASH',
|
||||
'PIVX': 'PIVX',
|
||||
'Wownero': 'WOW',
|
||||
'Decred': 'DCR',
|
||||
'Zano': 'ZANO',
|
||||
'PIVX': 'PIVX'
|
||||
};
|
||||
|
||||
const getUsdValue = (cryptoValue, coinSymbol) => {
|
||||
@@ -271,47 +255,28 @@ const updateValues = async () => {
|
||||
calculateTotalBtcValue();
|
||||
};
|
||||
|
||||
const toggleUsdAmount = async (usdCell, isVisible) => {
|
||||
const toggleUsdAmount = (usdCell, isVisible) => {
|
||||
const usdText = document.getElementById('usd-text');
|
||||
if (usdText) {
|
||||
usdText.style.display = isVisible ? 'inline' : 'none';
|
||||
}
|
||||
|
||||
const usdText = document.getElementById('usd-text');
|
||||
|
||||
|
||||
if (usdText) {
|
||||
usdText.style.display = isVisible ? 'inline' : 'none';
|
||||
}
|
||||
|
||||
if (isVisible) {
|
||||
const coinNameValueElement = usdCell.parentElement.querySelector('.coinname-value');
|
||||
|
||||
|
||||
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) {
|
||||
await updateValues();
|
||||
} else {
|
||||
console.error(`Coin symbol not found for full name: ${coinFullName}`);
|
||||
}
|
||||
} else {
|
||||
console.error(`Data attribute 'data-coinname' not found.`);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
if (isVisible) {
|
||||
const coinFullName = usdCell.previousElementSibling.getAttribute('data-coinname');
|
||||
const cryptoValue = parseFloat(usdCell.previousElementSibling.textContent);
|
||||
const coinSymbol = coinNameToSymbol[coinFullName];
|
||||
if (coinSymbol) {
|
||||
updateValues();
|
||||
} else {
|
||||
usdCell.textContent = "******";
|
||||
const btcValueElement = usdCell.nextElementSibling;
|
||||
if (btcValueElement) {
|
||||
btcValueElement.textContent = "****";
|
||||
}
|
||||
console.error(`Coin symbol not found for full name: ${coinFullName}`);
|
||||
}
|
||||
} else {
|
||||
usdCell.textContent = "******";
|
||||
const btcValueElement = usdCell.nextElementSibling;
|
||||
if (btcValueElement) {
|
||||
btcValueElement.textContent = "****";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const toggleUsdIcon = (isVisible) => {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{% include 'header.html' %}
|
||||
{% from 'style.html' import breadcrumb_line_svg, circular_arrows_svg %}
|
||||
<div class="container mx-auto">
|
||||
<section class="p-5 mt-5">
|
||||
<div class="flex flex-wrap items-center -m-2">
|
||||
@@ -10,11 +9,19 @@
|
||||
<p>Home</p>
|
||||
</a>
|
||||
</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>
|
||||
<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>{{ 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>
|
||||
</div>
|
||||
</div>
|
||||
@@ -32,13 +39,23 @@
|
||||
</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">
|
||||
{% 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">
|
||||
{{ circular_arrows_svg | safe }}
|
||||
<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">
|
||||
<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>
|
||||
{% 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">
|
||||
{{ circular_arrows_svg | safe }}
|
||||
<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">
|
||||
<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>
|
||||
{% endif %}
|
||||
|
||||
@@ -108,7 +108,11 @@ def page_bid(self, url_split, post_string):
|
||||
|
||||
if len(data['addr_from_label']) > 0:
|
||||
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:
|
||||
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,
|
||||
'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],
|
||||
'bids_count': len(bids),
|
||||
})
|
||||
|
||||
@@ -5,19 +5,17 @@
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
import traceback
|
||||
import time
|
||||
|
||||
from urllib import parse
|
||||
from .util import (
|
||||
getCoinType,
|
||||
get_data_entry,
|
||||
get_data_entry_or,
|
||||
have_data_entry,
|
||||
inputAmount,
|
||||
known_chart_coins,
|
||||
listAvailableCoins,
|
||||
PAGE_LIMIT,
|
||||
getCoinType,
|
||||
inputAmount,
|
||||
setCoinFilter,
|
||||
get_data_entry,
|
||||
have_data_entry,
|
||||
get_data_entry_or,
|
||||
listAvailableCoins,
|
||||
set_pagination_filters,
|
||||
)
|
||||
from basicswap.db import (
|
||||
@@ -26,6 +24,7 @@ from basicswap.db import (
|
||||
from basicswap.util import (
|
||||
ensure,
|
||||
format_amount,
|
||||
format_timestamp,
|
||||
)
|
||||
from basicswap.basicswap_util import (
|
||||
SwapTypes,
|
||||
@@ -41,8 +40,8 @@ from basicswap.chainparams import (
|
||||
Coins,
|
||||
)
|
||||
|
||||
|
||||
default_chart_api_key = '95dd900af910656e0e17c41f2ddc5dba77d01bf8b0e7d2787634a16bd976c553'
|
||||
default_coingecko_api_key = 'CG-8hm3r9iLfpEXv4ied8oLbeUj'
|
||||
|
||||
|
||||
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)
|
||||
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
|
||||
parsed_data['amt_var'] = page_data['amt_var']
|
||||
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))
|
||||
parsed_data['to_fee_override'] = page_data['to_fee_override']
|
||||
except Exception as e:
|
||||
# Error is expected if missing fields
|
||||
if swap_client.debug is True:
|
||||
swap_client.log.warning(f'parseOfferFormData failed to set fee: Error {e}')
|
||||
print('Error setting fee', str(e)) # Expected if missing fields
|
||||
|
||||
return parsed_data, errors
|
||||
|
||||
@@ -312,8 +306,6 @@ def postNewOfferFromParsed(swap_client, parsed_data):
|
||||
extra_options['automation_id'] = parsed_data['automation_strat_id']
|
||||
|
||||
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):
|
||||
ci_from = swap_client.ci(parsed_data['coin_from'])
|
||||
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_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 = {
|
||||
'formid': self.generate_form_id(),
|
||||
'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_bid_min': ci_from.format_amount(offer.min_bid_amount),
|
||||
'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),
|
||||
'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 = 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, {
|
||||
'messages': 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)],
|
||||
'show_chart': swap_client.settings.get('show_chart', True),
|
||||
'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))
|
||||
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()
|
||||
data = {
|
||||
'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_to_ind': int(ci_to.coin_type()),
|
||||
'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),
|
||||
'rate': ci_to.format_amount(offer.rate),
|
||||
'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):
|
||||
server = self.server
|
||||
swap_client = server.swap_client
|
||||
@@ -775,29 +721,19 @@ def page_offers(self, url_split, post_string, sent=False):
|
||||
|
||||
now: int = swap_client.getTime()
|
||||
formatted_offers = []
|
||||
tla_from = ""
|
||||
tla_to = ""
|
||||
|
||||
for row in offers:
|
||||
o, completed_amount = row
|
||||
ci_from = swap_client.ci(Coins(o.coin_from))
|
||||
ci_to = swap_client.ci(Coins(o.coin_to))
|
||||
is_expired = o.expire_at <= now
|
||||
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_created_at,
|
||||
format_timestamp(o.created_at),
|
||||
o.offer_id.hex(),
|
||||
ci_from.coin_name(),
|
||||
ci_to.coin_name(),
|
||||
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),
|
||||
'Public' if o.addr_to == swap_client.network_addr else o.addr_to,
|
||||
o.addr_from,
|
||||
@@ -805,12 +741,8 @@ def page_offers(self, url_split, post_string, sent=False):
|
||||
ci_from.format_amount(completed_amount),
|
||||
is_expired,
|
||||
o.active_ind,
|
||||
formatted_expired_at,
|
||||
strSwapDesc(o.swap_type),
|
||||
amount_negotiable,
|
||||
tla_from,
|
||||
tla_to
|
||||
))
|
||||
amount_negotiable))
|
||||
|
||||
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 = 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')
|
||||
return self.render_template(template, {
|
||||
'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.',
|
||||
'messages': messages,
|
||||
'show_chart': False if sent else swap_client.settings.get('show_chart', True),
|
||||
'chart_api_key': chart_api_key,
|
||||
'coingecko_api_key': coingecko_api_key,
|
||||
'coins_from': coins_from,
|
||||
'coins': coins_to,
|
||||
'messages': messages,
|
||||
@@ -863,8 +766,4 @@ def page_offers(self, url_split, post_string, sent=False):
|
||||
'offers': formatted_offers,
|
||||
'summary': summary,
|
||||
'sent_offers': sent,
|
||||
'offers_count': offers_count,
|
||||
'tla_from': tla_from,
|
||||
'tla_to': tla_to,
|
||||
'enabled_chart_coins': enabled_chart_coins,
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2022-2024 tecnovert
|
||||
# Copyright (c) 2022-2023 tecnovert
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
@@ -45,8 +45,6 @@ def page_settings(self, url_split, post_string):
|
||||
data = {
|
||||
'show_chart': toBool(get_data_entry(form_data, 'showchart')),
|
||||
'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)
|
||||
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'))
|
||||
else:
|
||||
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 = {
|
||||
'show_chart': swap_client.settings.get('show_chart', True),
|
||||
'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
|
||||
|
||||
@@ -133,53 +133,36 @@ def page_wallet(self, url_split, post_string):
|
||||
page_data = {}
|
||||
messages = []
|
||||
err_messages = []
|
||||
show_utxo_groups: bool = False
|
||||
withdrawal_successful: bool = False
|
||||
force_refresh: bool = False
|
||||
show_utxo_groups = False
|
||||
form_data = self.checkForm(post_string, 'wallet', err_messages)
|
||||
if form_data:
|
||||
cid = str(int(coin_id))
|
||||
|
||||
estimate_fee: bool = have_data_entry(form_data, 'estfee_' + cid)
|
||||
withdraw: bool = have_data_entry(form_data, 'withdraw_' + cid)
|
||||
if have_data_entry(form_data, 'newaddr_' + cid):
|
||||
if bytes('newaddr_' + cid, 'utf-8') in form_data:
|
||||
swap_client.cacheNewAddressForCoin(coin_id)
|
||||
elif have_data_entry(form_data, 'forcerefresh'):
|
||||
force_refresh = True
|
||||
elif have_data_entry(form_data, 'newmwebaddr_' + cid):
|
||||
elif bytes('newmwebaddr_' + cid, 'utf-8') in form_data:
|
||||
swap_client.cacheNewStealthAddressForCoin(coin_id)
|
||||
elif have_data_entry(form_data, 'reseed_' + cid):
|
||||
elif bytes('reseed_' + cid, 'utf-8') in form_data:
|
||||
try:
|
||||
swap_client.reseedWallet(coin_id)
|
||||
messages.append('Reseed complete ' + str(coin_id))
|
||||
except Exception as ex:
|
||||
err_messages.append('Reseed failed ' + str(ex))
|
||||
swap_client.updateWalletsInfo(True, coin_id)
|
||||
elif withdraw or estimate_fee:
|
||||
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:
|
||||
value = form_data[bytes('amt_' + cid, 'utf-8')][0].decode('utf-8')
|
||||
page_data['wd_value_' + cid] = value
|
||||
except Exception as e:
|
||||
err_messages.append('Missing value')
|
||||
elif bytes('withdraw_' + cid, 'utf-8') in form_data:
|
||||
try:
|
||||
value = form_data[bytes('amt_' + cid, 'utf-8')][0].decode('utf-8')
|
||||
page_data['wd_value_' + cid] = value
|
||||
except Exception as e:
|
||||
err_messages.append('Missing value')
|
||||
try:
|
||||
address = form_data[bytes('to_' + cid, 'utf-8')][0].decode('utf-8')
|
||||
page_data['wd_address_' + cid] = address
|
||||
except Exception as e:
|
||||
err_messages.append('Missing address')
|
||||
|
||||
if estimate_fee and withdraw:
|
||||
err_messages.append('Estimate fee and withdraw can\'t be used together.')
|
||||
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}.')
|
||||
subfee = True if bytes('subfee_' + cid, 'utf-8') in form_data else False
|
||||
page_data['wd_subfee_' + cid] = subfee
|
||||
|
||||
if coin_id == Coins.PART:
|
||||
try:
|
||||
@@ -196,9 +179,9 @@ def page_wallet(self, url_split, post_string):
|
||||
except Exception as e:
|
||||
err_messages.append('Missing type')
|
||||
|
||||
if len(err_messages) == 0:
|
||||
if len(messages) == 0:
|
||||
ci = swap_client.ci(coin_id)
|
||||
ticker: str = ci.ticker()
|
||||
ticker = ci.ticker()
|
||||
try:
|
||||
if coin_id == Coins.PART:
|
||||
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:
|
||||
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))
|
||||
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:
|
||||
txid = swap_client.withdrawCoin(coin_id, value, address, subfee)
|
||||
messages.append('Withdrew {} {} to address {}<br/>In txid: {}'.format(value, ticker, address, txid))
|
||||
if not estimate_fee:
|
||||
withdrawal_successful = True
|
||||
except Exception as e:
|
||||
if swap_client.debug is True:
|
||||
swap_client.log.error(traceback.format_exc())
|
||||
err_messages.append(str(e))
|
||||
if not estimate_fee:
|
||||
swap_client.updateWalletsInfo(True, only_coin=coin_id)
|
||||
swap_client.updateWalletsInfo(True, coin_id)
|
||||
elif have_data_entry(form_data, 'showutxogroups'):
|
||||
show_utxo_groups = True
|
||||
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
|
||||
|
||||
ci = swap_client.ci(coin_id)
|
||||
|
||||
value_sats = ci.make_int(value)
|
||||
|
||||
txid, address = ci.createUTXO(value_sats)
|
||||
@@ -250,7 +214,7 @@ def page_wallet(self, url_split, post_string):
|
||||
if swap_client.debug is True:
|
||||
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})
|
||||
for k in wallets.keys():
|
||||
w = wallets[k]
|
||||
@@ -291,22 +255,15 @@ def page_wallet(self, url_split, post_string):
|
||||
if 'wd_type_to_' + cid in page_data:
|
||||
wallet_data['wd_type_to'] = page_data['wd_type_to_' + cid]
|
||||
|
||||
if 'wd_value_' + cid in page_data:
|
||||
wallet_data['wd_value'] = page_data['wd_value_' + cid]
|
||||
if 'wd_address_' + cid in page_data:
|
||||
wallet_data['wd_address'] = page_data['wd_address_' + cid]
|
||||
if 'wd_subfee_' + cid in page_data:
|
||||
wallet_data['wd_subfee'] = page_data['wd_subfee_' + 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:
|
||||
wallet_data['wd_value'] = page_data['wd_value_' + cid]
|
||||
if 'wd_address_' + cid in page_data:
|
||||
wallet_data['wd_address'] = page_data['wd_address_' + cid]
|
||||
if 'wd_subfee_' + cid in page_data:
|
||||
wallet_data['wd_subfee'] = page_data['wd_subfee_' + cid]
|
||||
if 'wd_sweepall_' + cid in page_data:
|
||||
wallet_data['wd_sweepall'] = page_data['wd_sweepall_' + cid]
|
||||
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:
|
||||
utxo_groups = ''
|
||||
unspent_by_addr = ci.getUnspentsByAddr()
|
||||
|
||||
@@ -31,9 +31,8 @@ from basicswap.basicswap_util import (
|
||||
|
||||
from basicswap.protocols.xmr_swap_1 import getChainBSplitKey, getChainBRemoteSplitKey
|
||||
|
||||
PAGE_LIMIT = 25
|
||||
PAGE_LIMIT = 50
|
||||
invalid_coins_from = []
|
||||
known_chart_coins = ['BTC', 'PART', 'XMR', 'LTC', 'FIRO', 'DASH', 'PIVX', 'DOGE', 'ETH', 'DCR', 'ZANO', 'WOW']
|
||||
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
initiator_role: str = 'offerer' # Leader
|
||||
participant_role: str = 'bidder' # Follower
|
||||
if reverse_bid:
|
||||
bid_amount = bid.amount_to
|
||||
bid_amount_to = bid.amount
|
||||
bid_rate = ci_from.make_int(bid.amount / bid.amount_to, r=1)
|
||||
initiator_role = 'bidder'
|
||||
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_to': ci_to.coin_name(),
|
||||
'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),
|
||||
'ticker_from': ci_from.ticker(),
|
||||
'ticker_to': ci_to.ticker(),
|
||||
|
||||
@@ -67,7 +67,6 @@ def dumpje(jin):
|
||||
|
||||
|
||||
def SerialiseNum(n: int) -> bytes:
|
||||
# For script
|
||||
if n == 0:
|
||||
return bytes((0x00,))
|
||||
if n > 0 and n <= 16:
|
||||
@@ -86,7 +85,6 @@ def SerialiseNum(n: int) -> bytes:
|
||||
|
||||
|
||||
def DeserialiseNum(b: bytes, o: int = 0) -> int:
|
||||
# For script
|
||||
if b[o] == 0:
|
||||
return 0
|
||||
if b[o] > 0x50 and b[o] <= 0x50 + 16:
|
||||
@@ -108,7 +106,7 @@ def float_to_str(f: float) -> str:
|
||||
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):
|
||||
v = float_to_str(v)
|
||||
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:
|
||||
raise ValueError('Mantissa too long')
|
||||
if r > 0:
|
||||
# Round off
|
||||
# Round up
|
||||
if int(c) > 4:
|
||||
rv += 1
|
||||
break
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2022-2024 tecnovert
|
||||
# Copyright (c) 2022-2023 tecnovert
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# 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.util.crypto import ripemd160, sha256
|
||||
from basicswap.util.crypto import ripemd160
|
||||
|
||||
__b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
|
||||
|
||||
@@ -67,7 +68,7 @@ def encodeStealthAddress(prefix_byte: int, scan_pubkey: bytes, spend_pubkey: byt
|
||||
data += bytes((0x00,)) # num prefix bits
|
||||
|
||||
b = bytes((prefix_byte,)) + data
|
||||
b += sha256(sha256(b))[:4]
|
||||
b += hashlib.sha256(hashlib.sha256(b).digest()).digest()[:4]
|
||||
return b58encode(b)
|
||||
|
||||
|
||||
@@ -82,15 +83,16 @@ def toWIF(prefix_byte: int, b: bytes, compressed: bool = True) -> str:
|
||||
b = bytes((prefix_byte,)) + b
|
||||
if compressed:
|
||||
b += bytes((0x01,))
|
||||
b += sha256(sha256(b))[:4]
|
||||
b += hashlib.sha256(hashlib.sha256(b).digest()).digest()[:4]
|
||||
return b58encode(b)
|
||||
|
||||
|
||||
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)
|
||||
if hrpgot != hrp:
|
||||
return None
|
||||
@@ -100,26 +102,25 @@ def bech32Decode(hrp: str, addr: str) -> bytes:
|
||||
return bytes(decoded)
|
||||
|
||||
|
||||
def bech32Encode(hrp: str, data: bytes) -> str:
|
||||
def bech32Encode(hrp, data):
|
||||
ret = bech32_encode(hrp, convertbits(data, 8, 5))
|
||||
if bech32Decode(hrp, ret) is None:
|
||||
return None
|
||||
return ret
|
||||
|
||||
|
||||
def decodeAddress(address: str) -> bytes:
|
||||
addr_data = b58decode(address)
|
||||
if addr_data is 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 decodeAddress(address_str: str):
|
||||
b58_addr = b58decode(address_str)
|
||||
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
|
||||
|
||||
|
||||
def encodeAddress(address: bytes) -> str:
|
||||
checksum = sha256(sha256(address))
|
||||
checksum = hashlib.sha256(hashlib.sha256(address).digest()).digest()
|
||||
return b58encode(address + checksum[0:4])
|
||||
|
||||
|
||||
|
||||
@@ -1,41 +1,23 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2022-2024 tecnovert
|
||||
# Copyright (c) 2022-2023 tecnovert
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
from basicswap.contrib.blake256.blake256 import blake_hash
|
||||
|
||||
from Crypto.Hash import HMAC, RIPEMD160, SHA256, SHA512 # pycryptodome
|
||||
from Crypto.Hash import RIPEMD160, SHA256 # pycryptodome
|
||||
|
||||
|
||||
def sha256(data: bytes) -> bytes:
|
||||
def sha256(data):
|
||||
h = SHA256.new()
|
||||
h.update(data)
|
||||
return h.digest()
|
||||
|
||||
|
||||
def sha512(data: bytes) -> bytes:
|
||||
h = SHA512.new()
|
||||
h.update(data)
|
||||
return h.digest()
|
||||
|
||||
|
||||
def ripemd160(data: bytes) -> bytes:
|
||||
def ripemd160(data):
|
||||
h = RIPEMD160.new()
|
||||
h.update(data)
|
||||
return h.digest()
|
||||
|
||||
|
||||
def blake256(data: bytes) -> bytes:
|
||||
return blake_hash(data)
|
||||
|
||||
|
||||
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()
|
||||
def hash160(s):
|
||||
return ripemd160(sha256(s))
|
||||
|
||||
@@ -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:]
|
||||
@@ -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
|
||||
@@ -1,7 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import basicswap.contrib.Keccak as Keccak
|
||||
from basicswap.util.integer import encode_varint
|
||||
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
|
||||
|
||||
|
||||
def encode_address(view_point: bytes, spend_point: bytes, version=18) -> str:
|
||||
prefix_bytes = version if isinstance(version, bytes) else encode_varint(version)
|
||||
buf = prefix_bytes + spend_point + view_point
|
||||
def encode_address(view_point, spend_point, version=18):
|
||||
buf = bytes((version,)) + spend_point + view_point
|
||||
h = cn_fast_hash(buf)
|
||||
buf = buf + bytes.fromhex(h[0: 8])
|
||||
|
||||
|
||||
@@ -5,71 +5,65 @@
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# 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 platform
|
||||
import random
|
||||
import sys
|
||||
import json
|
||||
import time
|
||||
import mmap
|
||||
import stat
|
||||
import gnupg
|
||||
import socks
|
||||
import shutil
|
||||
import signal
|
||||
import socket
|
||||
import socks
|
||||
import stat
|
||||
import sys
|
||||
import hashlib
|
||||
import tarfile
|
||||
import threading
|
||||
import time
|
||||
import urllib.parse
|
||||
import zipfile
|
||||
|
||||
import logging
|
||||
import platform
|
||||
import contextlib
|
||||
import urllib.parse
|
||||
from urllib.error import ContentTooShortError
|
||||
from urllib.parse import _splittype
|
||||
from urllib.request import Request, urlopen
|
||||
from urllib.parse import _splittype
|
||||
|
||||
import basicswap.config as cfg
|
||||
from basicswap import __version__
|
||||
from basicswap.base import getaddrinfo_tor
|
||||
from basicswap.basicswap import BasicSwap
|
||||
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.util import toBool
|
||||
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
|
||||
|
||||
PARTICL_VERSION = os.getenv('PARTICL_VERSION', '23.2.7.0')
|
||||
PARTICL_VERSION_TAG = os.getenv('PARTICL_VERSION_TAG', '')
|
||||
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', '')
|
||||
|
||||
BITCOIN_VERSION = os.getenv('BITCOIN_VERSION', '26.0')
|
||||
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', '')
|
||||
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', '')
|
||||
|
||||
DASH_VERSION = os.getenv('DASH_VERSION', '20.0.2')
|
||||
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', '')
|
||||
|
||||
NAV_VERSION = os.getenv('NAV_VERSION', '7.0.3')
|
||||
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
|
||||
|
||||
ADD_PUBKEY_URL = os.getenv('ADD_PUBKEY_URL', '')
|
||||
@@ -89,12 +83,10 @@ known_coins = {
|
||||
'dash': (DASH_VERSION, DASH_VERSION_TAG, ('pasta',)),
|
||||
'firo': (FIRO_VERSION, FIRO_VERSION_TAG, ('reuben',)),
|
||||
'navcoin': (NAV_VERSION, NAV_VERSION_TAG, ('nav_builder',)),
|
||||
'decred': (DCR_VERSION, DCR_VERSION_TAG, ('decred_release',)),
|
||||
}
|
||||
|
||||
disabled_coins = [
|
||||
'navcoin',
|
||||
'namecoin', # Needs update
|
||||
]
|
||||
|
||||
expected_key_ids = {
|
||||
@@ -104,11 +96,10 @@ expected_key_ids = {
|
||||
'JeremyRand': ('2DBE339E29F6294C',),
|
||||
'binaryfate': ('F0AF4D462A0BDF92',),
|
||||
'davidburkett38': ('3620E9D387E55666',),
|
||||
'fuzzbawls': ('C1ABA64407731FD9',),
|
||||
'fuzzbawls': ('3BDCDA2D87A881D9',),
|
||||
'pasta': ('52527BEDABE87984',),
|
||||
'reuben': ('1290A1D0FA7EE109',),
|
||||
'nav_builder': ('2782262BF6E7FADB',),
|
||||
'decred_release': ('6D897EDF518A031D',),
|
||||
}
|
||||
|
||||
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_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_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)
|
||||
|
||||
|
||||
def popConnectionParameters() -> None:
|
||||
def popConnectionParameters():
|
||||
if use_tor_proxy:
|
||||
socket.socket = default_socket
|
||||
socket.getaddrinfo = default_socket_getaddrinfo
|
||||
socket.setdefaulttimeout(default_socket_timeout)
|
||||
|
||||
|
||||
def downloadFile(url: str, path: str, timeout=5, resume_from=0) -> None:
|
||||
logger.info(f'Downloading file {url}')
|
||||
logger.info(f'To {path}')
|
||||
def downloadFile(url, path, timeout=5, resume_from=0):
|
||||
logger.info('Downloading file %s', url)
|
||||
logger.info('To %s', path)
|
||||
try:
|
||||
setConnectionParameters(timeout=timeout)
|
||||
urlretrieve(url, path, make_reporthook(resume_from), resume_from=resume_from)
|
||||
@@ -402,12 +385,13 @@ def importPubkeyFromUrls(gpg, pubkeyurls):
|
||||
try:
|
||||
logger.info('Importing public key from url: ' + url)
|
||||
rv = gpg.import_keys(downloadBytes(url))
|
||||
for key in rv.fingerprints:
|
||||
gpg.trust_keys(key, 'TRUST_FULLY')
|
||||
break
|
||||
except Exception as e:
|
||||
logging.warning('Import from url failed: %s', str(e))
|
||||
|
||||
for key in rv.fingerprints:
|
||||
gpg.trust_keys(key, 'TRUST_FULLY')
|
||||
|
||||
|
||||
def testTorConnection():
|
||||
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)
|
||||
return
|
||||
|
||||
bins = [coin + 'd', coin + '-cli', coin + '-tx']
|
||||
versions = version.split('.')
|
||||
dir_name = 'dashcore' if coin == 'dash' else coin
|
||||
if coin == 'decred':
|
||||
bins = ['dcrd', 'dcrwallet']
|
||||
else:
|
||||
bins = [coin + 'd', coin + '-cli', coin + '-tx']
|
||||
versions = version.split('.')
|
||||
if int(versions[0]) >= 22 or int(versions[1]) >= 19:
|
||||
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 int(versions[0]) >= 22 or int(versions[1]) >= 19:
|
||||
bins.append(coin + '-wallet')
|
||||
if 'win32' in BIN_ARCH or 'win64' in BIN_ARCH:
|
||||
with zipfile.ZipFile(release_path) as fz:
|
||||
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)
|
||||
if (not os.path.exists(out_path)) or extract_core_overwrite:
|
||||
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:
|
||||
os.chmod(out_path, stat.S_IRWXU | stat.S_IXGRP | stat.S_IXOTH)
|
||||
except Exception as e:
|
||||
@@ -571,7 +541,15 @@ def extractCore(coin, version_data, settings, bin_dir, release_path, extra_opts=
|
||||
for b in bins:
|
||||
out_path = os.path.join(bin_dir, b)
|
||||
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())
|
||||
try:
|
||||
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)
|
||||
if not os.path.exists(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:
|
||||
major_version = int(version.split('.')[0])
|
||||
|
||||
@@ -683,7 +628,8 @@ def prepareCore(coin, version_data, settings, data_dir, extra_opts={}):
|
||||
elif coin == 'litecoin':
|
||||
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_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':
|
||||
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]))
|
||||
@@ -777,8 +723,6 @@ def prepareCore(coin, version_data, settings, data_dir, extra_opts={}):
|
||||
|
||||
if coin in ('navcoin', ):
|
||||
pubkey_filename = '{}_builder.pgp'.format(coin)
|
||||
elif coin in ('decred', ):
|
||||
pubkey_filename = '{}_release.pgp'.format(coin)
|
||||
else:
|
||||
pubkey_filename = '{}_{}.pgp'.format(coin, signing_key_name)
|
||||
pubkeyurls = [
|
||||
@@ -920,40 +864,6 @@ def prepareDataDir(coin, settings, chain, particl_mnemonic, extra_opts={}):
|
||||
fp.write(opt_line + '\n')
|
||||
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')
|
||||
if os.path.exists(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)))
|
||||
elif coin == 'litecoin':
|
||||
fp.write('prune=4000\n')
|
||||
fp.write('blockfilterindex=0\n')
|
||||
fp.write('peerblockfilters=0\n')
|
||||
fp.write('pid=litecoind.pid\n')
|
||||
if LTC_RPC_USER != '':
|
||||
fp.write('rpcauth={}:{}${}\n'.format(LTC_RPC_USER, salt, password_to_hmac(salt, LTC_RPC_PWD)))
|
||||
elif coin == 'bitcoin':
|
||||
@@ -1011,6 +920,7 @@ def prepareDataDir(coin, settings, chain, particl_mnemonic, extra_opts={}):
|
||||
elif coin == 'pivx':
|
||||
params_dir = os.path.join(data_dir, 'pivx-params')
|
||||
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)
|
||||
fp.write(f'paramsdir={PIVX_PARAMSDIR}\n')
|
||||
if PIVX_RPC_USER != '':
|
||||
@@ -1217,13 +1127,13 @@ def printHelp():
|
||||
|
||||
|
||||
def finalise_daemon(d):
|
||||
logging.info('Interrupting {}'.format(d.handle.pid))
|
||||
logging.info('Interrupting {}'.format(d.pid))
|
||||
try:
|
||||
d.handle.send_signal(signal.CTRL_C_EVENT if os.name == 'nt' else signal.SIGINT)
|
||||
d.handle.wait(timeout=120)
|
||||
d.send_signal(signal.CTRL_C_EVENT if os.name == 'nt' else signal.SIGINT)
|
||||
d.wait(timeout=120)
|
||||
except Exception as e:
|
||||
logging.info(f'Error {e} for process {d.handle.pid}')
|
||||
for fp in [d.handle.stdout, d.handle.stderr, d.handle.stdin] + d.files:
|
||||
logging.info(f'Error {e} for process {d.pid}')
|
||||
for fp in (d.stdout, d.stderr, d.stdin):
|
||||
if fp:
|
||||
fp.close()
|
||||
|
||||
@@ -1244,7 +1154,7 @@ def test_particl_encryption(data_dir, settings, chain, use_tor_proxy):
|
||||
if coin_settings['manage_daemon']:
|
||||
filename = coin_name + 'd' + ('.exe' if os.name == 'nt' else '')
|
||||
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.createCoinInterface(c)
|
||||
swap_client.waitForDaemonRPC(c, with_wallet=True)
|
||||
@@ -1273,8 +1183,6 @@ def initialise_wallets(particl_wallet_mnemonic, with_coins, data_dir, settings,
|
||||
daemons = []
|
||||
daemon_args = ['-noconnect', '-nodnsseed']
|
||||
|
||||
coins_failed_to_initialise = []
|
||||
|
||||
with open(os.path.join(data_dir, 'basicswap.log'), 'a') as fp:
|
||||
try:
|
||||
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']:
|
||||
filename = 'monero-wallet-rpc' + ('.exe' if os.name == 'nt' else '')
|
||||
daemons.append(startXmrWalletDaemon(coin_settings['datadir'], coin_settings['bindir'], filename))
|
||||
elif c == Coins.DCR:
|
||||
pass
|
||||
else:
|
||||
if coin_settings['manage_daemon']:
|
||||
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())]
|
||||
|
||||
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.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:
|
||||
swap_client.waitForDaemonRPC(c, with_wallet=False)
|
||||
# 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)
|
||||
if c in (Coins.PART, ):
|
||||
continue
|
||||
if c not in (Coins.DCR, ):
|
||||
# initialiseWallet only sets main_wallet_seedid_
|
||||
swap_client.waitForDaemonRPC(c)
|
||||
try:
|
||||
swap_client.initialiseWallet(c, raise_errors=True)
|
||||
except Exception as e:
|
||||
coins_failed_to_initialise.append((c, e))
|
||||
swap_client.waitForDaemonRPC(c)
|
||||
swap_client.initialiseWallet(c)
|
||||
if WALLET_ENCRYPTION_PWD != '' and c not in coins_to_create_wallets_for:
|
||||
try:
|
||||
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:
|
||||
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:
|
||||
# Print directly to stdout for tests
|
||||
@@ -1666,19 +1543,7 @@ def main():
|
||||
'override_feerate': 0.002,
|
||||
'conf_target': 2,
|
||||
'core_version_group': 21,
|
||||
},
|
||||
'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,
|
||||
'chain_lookups': 'local',
|
||||
},
|
||||
'litecoin': {
|
||||
'connection_type': 'rpc' if 'litecoin' in with_coins else 'none',
|
||||
@@ -1693,26 +1558,21 @@ def main():
|
||||
'conf_target': 2,
|
||||
'core_version_group': 21,
|
||||
'min_relay_fee': 0.00001,
|
||||
'chain_lookups': 'local',
|
||||
},
|
||||
'decred': {
|
||||
'connection_type': 'rpc' if 'decred' in with_coins else 'none',
|
||||
'manage_daemon': True if ('decred' in with_coins and DCR_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,
|
||||
'wallet_pwd': DCR_WALLET_PWD if WALLET_ENCRYPTION_PWD == '' else '',
|
||||
'rpchost': DCR_RPC_HOST,
|
||||
'rpcport': DCR_RPC_PORT + port_offset,
|
||||
'walletrpchost': DCR_WALLET_RPC_HOST,
|
||||
'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,
|
||||
'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': 2,
|
||||
'blocks_confirmed': 1,
|
||||
'conf_target': 2,
|
||||
'core_type_group': 'dcr',
|
||||
'min_relay_fee': 0.00001,
|
||||
'core_version_group': 22,
|
||||
'chain_lookups': 'local',
|
||||
},
|
||||
'namecoin': {
|
||||
'connection_type': 'rpc' if 'namecoin' in with_coins else 'none',
|
||||
@@ -1748,7 +1608,6 @@ def main():
|
||||
'rpctimeout': 60,
|
||||
'walletrpctimeout': 120,
|
||||
'walletrpctimeoutlong': 600,
|
||||
'core_type_group': 'xmr',
|
||||
},
|
||||
'pivx': {
|
||||
'connection_type': 'rpc' if 'pivx' in with_coins else 'none',
|
||||
@@ -1763,6 +1622,7 @@ def main():
|
||||
'blocks_confirmed': 1,
|
||||
'conf_target': 2,
|
||||
'core_version_group': 17,
|
||||
'chain_lookups': 'local',
|
||||
},
|
||||
'dash': {
|
||||
'connection_type': 'rpc' if 'dash' in with_coins else 'none',
|
||||
@@ -1777,6 +1637,7 @@ def main():
|
||||
'blocks_confirmed': 1,
|
||||
'conf_target': 2,
|
||||
'core_version_group': 18,
|
||||
'chain_lookups': 'local',
|
||||
},
|
||||
'firo': {
|
||||
'connection_type': 'rpc' if 'firo' in with_coins else 'none',
|
||||
@@ -1792,6 +1653,7 @@ def main():
|
||||
'conf_target': 2,
|
||||
'core_version_group': 14,
|
||||
'min_relay_fee': 0.00001,
|
||||
'chain_lookups': 'local',
|
||||
},
|
||||
'navcoin': {
|
||||
'connection_type': 'rpc' if 'navcoin' in with_coins else 'none',
|
||||
|
||||
@@ -18,7 +18,6 @@ import basicswap.config as cfg
|
||||
from basicswap import __version__
|
||||
from basicswap.ui.util import getCoinName
|
||||
from basicswap.basicswap import BasicSwap
|
||||
from basicswap.chainparams import chainparams
|
||||
from basicswap.http_server import HttpThread
|
||||
from basicswap.contrib.websocket_server import WebsocketServer
|
||||
|
||||
@@ -29,21 +28,18 @@ if not len(logger.handlers):
|
||||
logger.addHandler(logging.StreamHandler(sys.stdout))
|
||||
|
||||
swap_client = None
|
||||
|
||||
|
||||
class Daemon:
|
||||
__slots__ = ('handle', 'files')
|
||||
|
||||
def __init__(self, handle, files):
|
||||
self.handle = handle
|
||||
self.files = files
|
||||
|
||||
|
||||
def is_known_coin(coin_name: str) -> bool:
|
||||
for k, v in chainparams.items():
|
||||
if coin_name == v['name']:
|
||||
return True
|
||||
return False
|
||||
# TODO: deduplicate
|
||||
known_coins = [
|
||||
'particl',
|
||||
'litecoin',
|
||||
'bitcoin',
|
||||
'namecoin',
|
||||
'monero',
|
||||
'pivx',
|
||||
'dash',
|
||||
'firo',
|
||||
'navcoin',
|
||||
]
|
||||
|
||||
|
||||
def signal_handler(sig, frame):
|
||||
@@ -53,45 +49,13 @@ def signal_handler(sig, frame):
|
||||
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))
|
||||
|
||||
datadir_path = os.path.expanduser(node_dir)
|
||||
|
||||
# Rewrite litecoin.conf for 0.21.3
|
||||
ltc_conf_path = os.path.join(datadir_path, 'litecoin.conf')
|
||||
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)
|
||||
args = [daemon_bin, '-datadir=' + datadir_path] + opts
|
||||
logging.info('Starting node ' + daemon_bin + ' ' + '-datadir=' + node_dir)
|
||||
return subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=datadir_path)
|
||||
|
||||
|
||||
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)
|
||||
file_stdout = open(os.path.join(datadir_path, 'core_stdout.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=[]):
|
||||
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)
|
||||
config_path = os.path.join(data_dir, 'monero_wallet.conf')
|
||||
if os.path.exists(config_path):
|
||||
args += ['--config-file=' + config_path]
|
||||
with open(config_path) as fp:
|
||||
for line in fp:
|
||||
if any(line.startswith(config_line) for config_line in config_to_remove):
|
||||
logging.warning('Found old config in monero_wallet.conf: {}'.format(line.strip()))
|
||||
needs_rewrite = True
|
||||
args += opts
|
||||
args = [daemon_bin, '--non-interactive', '--config-file=' + config_path] + opts
|
||||
|
||||
if needs_rewrite:
|
||||
# TODO: Remove
|
||||
# Remove daemon-address
|
||||
has_daemon_address = False
|
||||
has_untrusted = False
|
||||
with open(config_path) as fp:
|
||||
for line in fp:
|
||||
if line.startswith('daemon-address'):
|
||||
has_daemon_address = True
|
||||
if line.startswith('untrusted-daemon'):
|
||||
has_untrusted = True
|
||||
if has_daemon_address:
|
||||
logging.info('Rewriting monero_wallet.conf')
|
||||
shutil.copyfile(config_path, config_path + '.last')
|
||||
with open(config_path + '.last') as fp_from, open(config_path, 'w') as fp_to:
|
||||
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)
|
||||
if not has_untrusted:
|
||||
fp_to.write('untrusted-daemon=1\n')
|
||||
|
||||
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)
|
||||
wallet_stdout = open(os.path.join(data_dir, 'wallet_stdout.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):
|
||||
@@ -169,11 +134,7 @@ def runClient(fp, data_dir, chain, start_only_coins):
|
||||
pids_path = os.path.join(data_dir, '.pids')
|
||||
|
||||
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):
|
||||
raise ValueError('Settings file not found: ' + str(settings_path))
|
||||
@@ -192,8 +153,6 @@ def runClient(fp, data_dir, chain, start_only_coins):
|
||||
# Ensure daemons are stopped
|
||||
swap_client.stopDaemons()
|
||||
|
||||
# Settings may have been modified
|
||||
settings = swap_client.settings
|
||||
try:
|
||||
# Try start daemons
|
||||
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')
|
||||
filename = 'monerod' + ('.exe' if os.name == 'nt' else '')
|
||||
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))
|
||||
|
||||
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')
|
||||
filename = 'monero-wallet-rpc' + ('.exe' if os.name == 'nt' else '')
|
||||
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))
|
||||
|
||||
continue # /monero
|
||||
|
||||
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
|
||||
|
||||
continue
|
||||
if v['manage_daemon'] is True:
|
||||
swap_client.log.info(f'Starting {display_name} daemon')
|
||||
|
||||
filename = c + 'd' + ('.exe' if os.name == 'nt' else '')
|
||||
daemons.append(startDaemon(v['datadir'], v['bindir'], filename))
|
||||
pid = daemons[-1].handle.pid
|
||||
pid = daemons[-1].pid
|
||||
pids.append((c, pid))
|
||||
swap_client.setDaemonPID(c, pid)
|
||||
swap_client.log.info('Started {} {}'.format(filename, pid))
|
||||
@@ -336,18 +265,18 @@ def runClient(fp, data_dir, chain, start_only_coins):
|
||||
|
||||
closed_pids = []
|
||||
for d in daemons:
|
||||
swap_client.log.info('Interrupting {}'.format(d.handle.pid))
|
||||
swap_client.log.info('Interrupting {}'.format(d.pid))
|
||||
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:
|
||||
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:
|
||||
try:
|
||||
d.handle.wait(timeout=120)
|
||||
for fp in [d.handle.stdout, d.handle.stderr, d.handle.stdin] + d.files:
|
||||
d.wait(timeout=120)
|
||||
for fp in (d.stdout, d.stderr, d.stdin):
|
||||
if fp:
|
||||
fp.close()
|
||||
closed_pids.append(d.handle.pid)
|
||||
closed_pids.append(d.pid)
|
||||
except Exception as ex:
|
||||
swap_client.log.error('Error: {}'.format(ex))
|
||||
|
||||
@@ -414,7 +343,7 @@ def main():
|
||||
continue
|
||||
if name == 'startonlycoin':
|
||||
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}')
|
||||
start_only_coins.add(coin)
|
||||
continue
|
||||
|
||||
@@ -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/
|
||||
|
||||
|
||||
#### 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:
|
||||
|
||||
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
|
||||
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):
|
||||
|
||||
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):
|
||||
|
||||
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.**
|
||||
**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.
|
||||
|
||||
#### 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):
|
||||
|
||||
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:
|
||||
|
||||
export COINDATA_PATH=/var/data/coinswaps
|
||||
docker-compose up
|
||||
|
||||
Open in browser: `http://localhost:12700`
|
||||
@@ -96,7 +94,8 @@ Open in browser: `http://localhost:12700`
|
||||
### Add a coin
|
||||
|
||||
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`
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
@@ -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
|
||||
==============
|
||||
|
||||
@@ -34,11 +18,6 @@
|
||||
- `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.
|
||||
- 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
|
||||
|
||||
@@ -12,6 +12,8 @@ Update only the code (prepend sudo to each docker command if necessary):
|
||||
|
||||
basicswap]$ git pull
|
||||
cd docker
|
||||
export COINDATA_PATH=[PATH_TO]
|
||||
(Probably export COINDATA_PATH=/var/data/coinswaps)
|
||||
docker-compose build
|
||||
docker-compose up
|
||||
|
||||
@@ -19,6 +21,7 @@ If the dependencies have changed the container must be built with `--no-cache`:
|
||||
|
||||
basicswap]$ git pull
|
||||
cd docker
|
||||
export COINDATA_PATH=[PATH_TO]
|
||||
docker-compose build --no-cache
|
||||
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:
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
HTML_PORT=127.0.0.1:12700:12700
|
||||
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
|
||||
TZ=UTC
|
||||
@@ -1,96 +0,0 @@
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
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
|
||||
O6GuapL0x1I9SeIk9WX9VRrpZmENhlri
|
||||
=JrM6
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
@@ -1,78 +1,589 @@
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Comment: Hostname:
|
||||
Version: Hockeypuck 2.1.0-166-geb2a11b
|
||||
|
||||
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
|
||||
Ng==
|
||||
=muu4
|
||||
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
|
||||
tXo=
|
||||
=lheU
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
@@ -463,7 +463,6 @@ def main():
|
||||
print(f'Not bidding on offer {offer_id}, too many failed bids ({failed_sent_bids}).')
|
||||
continue
|
||||
|
||||
validateamount: bool = False
|
||||
max_coin_from_balance = bid_template.get('max_coin_from_balance', -1)
|
||||
if max_coin_from_balance > 0:
|
||||
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 can_adjust_amount and max_coin_from_balance - total_balance_from > min_swap_amount:
|
||||
bid_amount = max_coin_from_balance - total_balance_from
|
||||
validateamount = True
|
||||
print(f'Reduced bid amount to {bid_amount}')
|
||||
else:
|
||||
if args.debug:
|
||||
@@ -495,9 +493,8 @@ def main():
|
||||
adjusted_bid_amount = adjusted_swap_amount_to / offer_rate
|
||||
|
||||
if adjusted_bid_amount > min_swap_amount:
|
||||
bid_amount = adjusted_bid_amount
|
||||
validateamount = True
|
||||
print(f'Reduced bid amount to {bid_amount}')
|
||||
bid_amount = adjusted_bid_amount
|
||||
swap_amount_to = adjusted_bid_amount * offer_rate
|
||||
|
||||
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}')
|
||||
continue
|
||||
|
||||
if validateamount:
|
||||
bid_amount = read_json_api('validateamount', {'coin': coin_from_data['ticker'], 'amount': bid_amount, 'method': 'rounddown'})
|
||||
bid_data = {
|
||||
'offer_id': offer['offer_id'],
|
||||
'amount_from': bid_amount}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2020-2024 tecnovert
|
||||
# Copyright (c) 2020-2023 tecnovert
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# 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_ZMQ_PORT = 36792
|
||||
|
||||
DCR_BASE_PORT = 18555
|
||||
DCR_BASE_RPC_PORT = 9110
|
||||
|
||||
|
||||
PIVX_BASE_PORT = 34892
|
||||
PIVX_BASE_RPC_PORT = 35892
|
||||
PIVX_BASE_ZMQ_PORT = 36892
|
||||
@@ -112,19 +108,19 @@ def checkForks(ro):
|
||||
|
||||
def stopDaemons(daemons):
|
||||
for d in daemons:
|
||||
logging.info('Interrupting %d', d.handle.pid)
|
||||
logging.info('Interrupting %d', d.pid)
|
||||
try:
|
||||
d.handle.send_signal(signal.SIGINT)
|
||||
d.send_signal(signal.SIGINT)
|
||||
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:
|
||||
try:
|
||||
d.handle.wait(timeout=20)
|
||||
for fp in [d.handle.stdout, d.handle.stderr, d.handle.stdin] + d.files:
|
||||
d.wait(timeout=20)
|
||||
for fp in (d.stdout, d.stderr, d.stdin):
|
||||
if fp:
|
||||
fp.close()
|
||||
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:
|
||||
@@ -316,20 +312,6 @@ def make_rpc_func(node_id, base_rpc_port=BASE_RPC_PORT):
|
||||
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):
|
||||
states = {}
|
||||
|
||||
@@ -393,7 +375,7 @@ def extract_states_from_xu_file(file_path, prefix):
|
||||
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):
|
||||
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)))
|
||||
raise e
|
||||
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
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user