Compare commits
No commits in common. "e487c6ea5652655a9f69090dc2224971cdd0fe18" and "79ec088059aa51d4acde566ff2b45a05e8e59df8" have entirely different histories.
e487c6ea56
...
79ec088059
|
@ -2,7 +2,4 @@
|
|||
.env
|
||||
.DS_Store
|
||||
__pycache__
|
||||
db.sqlite3
|
||||
._.DS_Store
|
||||
._src
|
||||
env
|
||||
db.sqlite3
|
|
@ -1,129 +0,0 @@
|
|||
from dependencies.crypto import *
|
||||
from base58 import b58decode_check, b58encode_check
|
||||
import sys
|
||||
|
||||
class InvalidAddress(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class Address:
|
||||
VERSION_MAP = {
|
||||
'legacy': [
|
||||
('P2SH', 5, False),
|
||||
('P2PKH', 0, False),
|
||||
('P2SH-TESTNET', 196, True),
|
||||
('P2PKH-TESTNET', 111, True)
|
||||
],
|
||||
'cash': [
|
||||
('P2SH', 8, False),
|
||||
('P2PKH', 0, False),
|
||||
('P2SH-TESTNET', 8, True),
|
||||
('P2PKH-TESTNET', 0, True)
|
||||
]
|
||||
}
|
||||
MAINNET_PREFIX = 'bitcoincash'
|
||||
TESTNET_PREFIX = 'bchtest'
|
||||
|
||||
def __init__(self, version, payload, prefix=None):
|
||||
self.version = version
|
||||
self.payload = payload
|
||||
if prefix:
|
||||
self.prefix = prefix
|
||||
else:
|
||||
if Address._address_type('cash', self.version)[2]:
|
||||
self.prefix = self.TESTNET_PREFIX
|
||||
else:
|
||||
self.prefix = self.MAINNET_PREFIX
|
||||
|
||||
def __str__(self):
|
||||
return 'version: {}\npayload: {}\nprefix: {}'.format(self.version, self.payload, self.prefix)
|
||||
|
||||
def legacy_address(self):
|
||||
version_int = Address._address_type('legacy', self.version)[1]
|
||||
return b58encode_check(Address.code_list_to_string([version_int] + self.payload))
|
||||
|
||||
def cash_address(self):
|
||||
version_int = Address._address_type('cash', self.version)[1]
|
||||
payload = [version_int] + self.payload
|
||||
payload = convertbits(payload, 8, 5)
|
||||
checksum = calculate_checksum(self.prefix, payload)
|
||||
return self.prefix + ':' + b32encode(payload + checksum)
|
||||
|
||||
@staticmethod
|
||||
def code_list_to_string(code_list):
|
||||
if sys.version_info > (3, 0):
|
||||
output = bytes()
|
||||
for code in code_list:
|
||||
output += bytes([code])
|
||||
else:
|
||||
output = ''
|
||||
for code in code_list:
|
||||
output += chr(code)
|
||||
return output
|
||||
|
||||
@staticmethod
|
||||
def _address_type(address_type, version):
|
||||
for mapping in Address.VERSION_MAP[address_type]:
|
||||
if mapping[0] == version or mapping[1] == version:
|
||||
return mapping
|
||||
raise InvalidAddress('Could not determine address version')
|
||||
|
||||
@staticmethod
|
||||
def from_string(address_string):
|
||||
try:
|
||||
address_string = str(address_string)
|
||||
except Exception:
|
||||
raise InvalidAddress('Expected string as input')
|
||||
if ':' not in address_string:
|
||||
return Address._legacy_string(address_string)
|
||||
else:
|
||||
return Address._cash_string(address_string)
|
||||
|
||||
@staticmethod
|
||||
def _legacy_string(address_string):
|
||||
try:
|
||||
decoded = bytearray(b58decode_check(address_string))
|
||||
except ValueError:
|
||||
raise InvalidAddress('Could not decode legacy address')
|
||||
version = Address._address_type('legacy', decoded[0])[0]
|
||||
payload = list()
|
||||
for letter in decoded[1:]:
|
||||
payload.append(letter)
|
||||
return Address(version, payload)
|
||||
|
||||
@staticmethod
|
||||
def _cash_string(address_string):
|
||||
if address_string.upper() != address_string and address_string.lower() != address_string:
|
||||
raise InvalidAddress('Cash address contains uppercase and lowercase characters')
|
||||
address_string = address_string.lower()
|
||||
colon_count = address_string.count(':')
|
||||
if colon_count == 0:
|
||||
address_string = Address.MAINNET_PREFIX + ':' + address_string
|
||||
elif colon_count > 1:
|
||||
raise InvalidAddress('Cash address contains more than one colon character')
|
||||
prefix, base32string = address_string.split(':')
|
||||
decoded = b32decode(base32string)
|
||||
if not verify_checksum(prefix, decoded):
|
||||
raise InvalidAddress('Bad cash address checksum')
|
||||
converted = convertbits(decoded, 5, 8)
|
||||
version = Address._address_type('cash', converted[0])[0]
|
||||
if prefix == Address.TESTNET_PREFIX:
|
||||
version += '-TESTNET'
|
||||
payload = converted[1:-6]
|
||||
return Address(version, payload, prefix)
|
||||
|
||||
|
||||
def to_cash_address(address):
|
||||
return Address.from_string(address).cash_address()
|
||||
|
||||
|
||||
def to_legacy_address(address):
|
||||
return Address.from_string(address).legacy_address()
|
||||
|
||||
|
||||
def is_valid(address):
|
||||
try:
|
||||
Address.from_string(address)
|
||||
return True
|
||||
except InvalidAddress:
|
||||
return False
|
|
@ -1,70 +0,0 @@
|
|||
CHARSET = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l'
|
||||
|
||||
|
||||
def polymod(values):
|
||||
chk = 1
|
||||
generator = [
|
||||
(0x01, 0x98f2bc8e61),
|
||||
(0x02, 0x79b76d99e2),
|
||||
(0x04, 0xf33e5fb3c4),
|
||||
(0x08, 0xae2eabe2a8),
|
||||
(0x10, 0x1e4f43e470)]
|
||||
for value in values:
|
||||
top = chk >> 35
|
||||
chk = ((chk & 0x07ffffffff) << 5) ^ value
|
||||
for i in generator:
|
||||
if top & i[0] != 0:
|
||||
chk ^= i[1]
|
||||
return chk ^ 1
|
||||
|
||||
|
||||
def prefix_expand(prefix):
|
||||
return [ord(x) & 0x1f for x in prefix] + [0]
|
||||
|
||||
|
||||
def calculate_checksum(prefix, payload):
|
||||
poly = polymod(prefix_expand(prefix) + payload + [0, 0, 0, 0, 0, 0, 0, 0])
|
||||
out = list()
|
||||
for i in range(8):
|
||||
out.append((poly >> 5 * (7 - i)) & 0x1f)
|
||||
return out
|
||||
|
||||
|
||||
def verify_checksum(prefix, payload):
|
||||
return polymod(prefix_expand(prefix) + payload) == 0
|
||||
|
||||
|
||||
def b32decode(inputs):
|
||||
out = list()
|
||||
for letter in inputs:
|
||||
out.append(CHARSET.find(letter))
|
||||
return out
|
||||
|
||||
|
||||
def b32encode(inputs):
|
||||
out = ''
|
||||
for char_code in inputs:
|
||||
out += CHARSET[char_code]
|
||||
return out
|
||||
|
||||
|
||||
def convertbits(data, frombits, tobits, pad=True):
|
||||
acc = 0
|
||||
bits = 0
|
||||
ret = []
|
||||
maxv = (1 << tobits) - 1
|
||||
max_acc = (1 << (frombits + tobits - 1)) - 1
|
||||
for value in data:
|
||||
if value < 0 or (value >> frombits):
|
||||
return None
|
||||
acc = ((acc << frombits) | value) & max_acc
|
||||
bits += frombits
|
||||
while bits >= tobits:
|
||||
bits -= tobits
|
||||
ret.append((acc >> bits) & maxv)
|
||||
if pad:
|
||||
if bits:
|
||||
ret.append((acc << (tobits - bits)) & maxv)
|
||||
elif bits >= frombits or ((acc << (tobits - bits)) & maxv):
|
||||
return None
|
||||
return ret
|
|
@ -1,185 +0,0 @@
|
|||
# MoneroPy - A python toolbox for Monero
|
||||
# Copyright (C) 2016 The MoneroPy Developers.
|
||||
#
|
||||
# MoneroPy is released under the BSD 3-Clause license. Use and redistribution of
|
||||
# this software is subject to the license terms in the LICENSE file found in the
|
||||
# top-level directory of this distribution.
|
||||
#
|
||||
# Modified by emesik and rooterkyberian:
|
||||
# + optimized
|
||||
# + proper exceptions instead of returning errors as results
|
||||
|
||||
__alphabet = [
|
||||
ord(s) for s in "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
||||
]
|
||||
__b58base = 58
|
||||
__UINT64MAX = 2 ** 64
|
||||
__encodedBlockSizes = [0, 2, 3, 5, 6, 7, 9, 10, 11]
|
||||
__fullBlockSize = 8
|
||||
__fullEncodedBlockSize = 11
|
||||
|
||||
|
||||
def _hexToBin(hex_):
|
||||
if len(hex_) % 2 != 0:
|
||||
raise ValueError("Hex string has invalid length: %d" % len(hex_))
|
||||
return [int(hex_[i : i + 2], 16) for i in range(0, len(hex_), 2)]
|
||||
|
||||
|
||||
def _binToHex(bin_):
|
||||
return "".join("%02x" % int(b) for b in bin_)
|
||||
|
||||
|
||||
def _uint8be_to_64(data):
|
||||
if not (1 <= len(data) <= 8):
|
||||
raise ValueError("Invalid input length: %d" % len(data))
|
||||
|
||||
res = 0
|
||||
for b in data:
|
||||
res = res << 8 | b
|
||||
return res
|
||||
|
||||
|
||||
def _uint64_to_8be(num, size):
|
||||
if size < 1 or size > 8:
|
||||
raise ValueError("Invalid input length: %d" % size)
|
||||
res = [0] * size
|
||||
|
||||
twopow8 = 2 ** 8
|
||||
for i in range(size - 1, -1, -1):
|
||||
res[i] = num % twopow8
|
||||
num = num // twopow8
|
||||
|
||||
return res
|
||||
|
||||
|
||||
def encode_block(data, buf, index):
|
||||
l_data = len(data)
|
||||
|
||||
if l_data < 1 or l_data > __fullEncodedBlockSize:
|
||||
raise ValueError("Invalid block length: %d" % l_data)
|
||||
|
||||
num = _uint8be_to_64(data)
|
||||
i = __encodedBlockSizes[l_data] - 1
|
||||
|
||||
while num > 0:
|
||||
remainder = num % __b58base
|
||||
num = num // __b58base
|
||||
buf[index + i] = __alphabet[remainder]
|
||||
i -= 1
|
||||
|
||||
return buf
|
||||
|
||||
|
||||
def encode(hex):
|
||||
"""Encode hexadecimal string as base58 (ex: encoding a Monero address)."""
|
||||
data = _hexToBin(hex)
|
||||
l_data = len(data)
|
||||
|
||||
if l_data == 0:
|
||||
return ""
|
||||
|
||||
full_block_count = l_data // __fullBlockSize
|
||||
last_block_size = l_data % __fullBlockSize
|
||||
res_size = (
|
||||
full_block_count * __fullEncodedBlockSize + __encodedBlockSizes[last_block_size]
|
||||
)
|
||||
|
||||
res = bytearray([__alphabet[0]] * res_size)
|
||||
|
||||
for i in range(full_block_count):
|
||||
res = encode_block(
|
||||
data[(i * __fullBlockSize) : (i * __fullBlockSize + __fullBlockSize)],
|
||||
res,
|
||||
i * __fullEncodedBlockSize,
|
||||
)
|
||||
|
||||
if last_block_size > 0:
|
||||
res = encode_block(
|
||||
data[
|
||||
(full_block_count * __fullBlockSize) : (
|
||||
full_block_count * __fullBlockSize + last_block_size
|
||||
)
|
||||
],
|
||||
res,
|
||||
full_block_count * __fullEncodedBlockSize,
|
||||
)
|
||||
|
||||
return bytes(res).decode("ascii")
|
||||
|
||||
|
||||
def decode_block(data, buf, index):
|
||||
l_data = len(data)
|
||||
|
||||
if l_data < 1 or l_data > __fullEncodedBlockSize:
|
||||
raise ValueError("Invalid block length: %d" % l_data)
|
||||
|
||||
res_size = __encodedBlockSizes.index(l_data)
|
||||
if res_size <= 0:
|
||||
raise ValueError("Invalid block size: %d" % res_size)
|
||||
|
||||
res_num = 0
|
||||
order = 1
|
||||
for i in range(l_data - 1, -1, -1):
|
||||
digit = __alphabet.index(data[i])
|
||||
if digit < 0:
|
||||
raise ValueError("Invalid symbol: %s" % data[i])
|
||||
|
||||
product = order * digit + res_num
|
||||
if product > __UINT64MAX:
|
||||
raise ValueError(
|
||||
"Overflow: %d * %d + %d = %d" % (order, digit, res_num, product)
|
||||
)
|
||||
|
||||
res_num = product
|
||||
order = order * __b58base
|
||||
|
||||
if res_size < __fullBlockSize and 2 ** (8 * res_size) <= res_num:
|
||||
raise ValueError("Overflow: %d doesn't fit in %d bit(s)" % (res_num, res_size))
|
||||
|
||||
tmp_buf = _uint64_to_8be(res_num, res_size)
|
||||
buf[index : index + len(tmp_buf)] = tmp_buf
|
||||
|
||||
return buf
|
||||
|
||||
|
||||
def decode(enc):
|
||||
"""Decode a base58 string (ex: a Monero address) into hexidecimal form."""
|
||||
enc = bytearray(enc, encoding="ascii")
|
||||
l_enc = len(enc)
|
||||
|
||||
if l_enc == 0:
|
||||
return ""
|
||||
|
||||
full_block_count = l_enc // __fullEncodedBlockSize
|
||||
last_block_size = l_enc % __fullEncodedBlockSize
|
||||
try:
|
||||
last_block_decoded_size = __encodedBlockSizes.index(last_block_size)
|
||||
except ValueError:
|
||||
raise ValueError("Invalid encoded length: %d" % l_enc)
|
||||
|
||||
data_size = full_block_count * __fullBlockSize + last_block_decoded_size
|
||||
|
||||
data = bytearray(data_size)
|
||||
for i in range(full_block_count):
|
||||
data = decode_block(
|
||||
enc[
|
||||
(i * __fullEncodedBlockSize) : (
|
||||
i * __fullEncodedBlockSize + __fullEncodedBlockSize
|
||||
)
|
||||
],
|
||||
data,
|
||||
i * __fullBlockSize,
|
||||
)
|
||||
|
||||
if last_block_size > 0:
|
||||
data = decode_block(
|
||||
enc[
|
||||
(full_block_count * __fullEncodedBlockSize) : (
|
||||
full_block_count * __fullEncodedBlockSize + last_block_size
|
||||
)
|
||||
],
|
||||
data,
|
||||
full_block_count * __fullBlockSize,
|
||||
)
|
||||
|
||||
return _binToHex(data)
|
|
@ -1,36 +0,0 @@
|
|||
import requests
|
||||
|
||||
#from dependencies.request_api import RequestsApi
|
||||
#call = RequestsApi("https://google.com")
|
||||
#r = call.get("/")
|
||||
|
||||
class RequestsApi:
|
||||
def __init__(self, base_url, **kwargs):
|
||||
self.base_url = base_url
|
||||
self.session = requests.Session()
|
||||
for arg in kwargs:
|
||||
if isinstance(kwargs[arg], dict):
|
||||
kwargs[arg] = self.deep_merge(getattr(self.session, arg), kwargs[arg])
|
||||
setattr(self.session, arg, kwargs[arg])
|
||||
|
||||
def request(self, method, url, **kwargs):
|
||||
return self.session.request(method, self.base_url+url, allow_redirects = False, **kwargs)
|
||||
|
||||
def head(self, url, **kwargs):
|
||||
return self.session.head(self.base_url+url, allow_redirects = False, **kwargs)
|
||||
|
||||
def get(self, url, **kwargs):
|
||||
return self.session.get(self.base_url+url, allow_redirects = False, **kwargs)
|
||||
|
||||
def post(self, url, **kwargs):
|
||||
return self.session.post(self.base_url+url, allow_redirects = False, **kwargs)
|
||||
|
||||
@staticmethod
|
||||
def deep_merge(source, destination):<
|
||||
for key, value in source.items():
|
||||
if isinstance(value, dict):
|
||||
node = destination.setdefault(key, {})
|
||||
RequestsApi.deep_merge(value, node)
|
||||
else:
|
||||
destination[key] = value
|
||||
return destination
|
|
@ -1,139 +0,0 @@
|
|||
|
||||
# Copyright (c) 2017, 2020 Pieter Wuille
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
|
||||
"""Reference implementation for Bech32/Bech32m and segwit addresses."""
|
||||
|
||||
|
||||
from enum import Enum
|
||||
|
||||
class Encoding(Enum):
|
||||
"""Enumeration type to list the various supported encodings."""
|
||||
BECH32 = 1
|
||||
BECH32M = 2
|
||||
|
||||
CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
|
||||
BECH32M_CONST = 0x2bc830a3
|
||||
|
||||
def bech32_polymod(values):
|
||||
"""Internal function that computes the Bech32 checksum."""
|
||||
generator = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3]
|
||||
chk = 1
|
||||
for value in values:
|
||||
top = chk >> 25
|
||||
chk = (chk & 0x1ffffff) << 5 ^ value
|
||||
for i in range(5):
|
||||
chk ^= generator[i] if ((top >> i) & 1) else 0
|
||||
return chk
|
||||
|
||||
|
||||
def bech32_hrp_expand(hrp):
|
||||
"""Expand the HRP into values for checksum computation."""
|
||||
return [ord(x) >> 5 for x in hrp] + [0] + [ord(x) & 31 for x in hrp]
|
||||
|
||||
|
||||
def bech32_verify_checksum(hrp, data):
|
||||
"""Verify a checksum given HRP and converted data characters."""
|
||||
const = bech32_polymod(bech32_hrp_expand(hrp) + data)
|
||||
if const == 1:
|
||||
return Encoding.BECH32
|
||||
if const == BECH32M_CONST:
|
||||
return Encoding.BECH32M
|
||||
return None
|
||||
|
||||
def bech32_create_checksum(hrp, data, spec):
|
||||
"""Compute the checksum values given HRP and data."""
|
||||
values = bech32_hrp_expand(hrp) + data
|
||||
const = BECH32M_CONST if spec == Encoding.BECH32M else 1
|
||||
polymod = bech32_polymod(values + [0, 0, 0, 0, 0, 0]) ^ const
|
||||
return [(polymod >> 5 * (5 - i)) & 31 for i in range(6)]
|
||||
|
||||
|
||||
def bech32_encode(hrp, data, spec):
|
||||
"""Compute a Bech32 string given HRP and data values."""
|
||||
combined = data + bech32_create_checksum(hrp, data, spec)
|
||||
return hrp + '1' + ''.join([CHARSET[d] for d in combined])
|
||||
|
||||
def bech32_decode(bech):
|
||||
"""Validate a Bech32/Bech32m string, and determine HRP and data."""
|
||||
if ((any(ord(x) < 33 or ord(x) > 126 for x in bech)) or
|
||||
(bech.lower() != bech and bech.upper() != bech)):
|
||||
return (None, None, None)
|
||||
bech = bech.lower()
|
||||
pos = bech.rfind('1')
|
||||
if pos < 1 or pos + 7 > len(bech) or len(bech) > 90:
|
||||
return (None, None, None)
|
||||
if not all(x in CHARSET for x in bech[pos+1:]):
|
||||
return (None, None, None)
|
||||
hrp = bech[:pos]
|
||||
data = [CHARSET.find(x) for x in bech[pos+1:]]
|
||||
spec = bech32_verify_checksum(hrp, data)
|
||||
if spec is None:
|
||||
return (None, None, None)
|
||||
return (hrp, data[:-6], spec)
|
||||
|
||||
def convertbits(data, frombits, tobits, pad=True):
|
||||
"""General power-of-2 base conversion."""
|
||||
acc = 0
|
||||
bits = 0
|
||||
ret = []
|
||||
maxv = (1 << tobits) - 1
|
||||
max_acc = (1 << (frombits + tobits - 1)) - 1
|
||||
for value in data:
|
||||
if value < 0 or (value >> frombits):
|
||||
return None
|
||||
acc = ((acc << frombits) | value) & max_acc
|
||||
bits += frombits
|
||||
while bits >= tobits:
|
||||
bits -= tobits
|
||||
ret.append((acc >> bits) & maxv)
|
||||
if pad:
|
||||
if bits:
|
||||
ret.append((acc << (tobits - bits)) & maxv)
|
||||
elif bits >= frombits or ((acc << (tobits - bits)) & maxv):
|
||||
return None
|
||||
return ret
|
||||
|
||||
|
||||
def decode(hrp, addr):
|
||||
"""Decode a segwit address."""
|
||||
hrpgot, data, spec = bech32_decode(addr)
|
||||
if hrpgot != hrp:
|
||||
return (None, None)
|
||||
decoded = convertbits(data[1:], 5, 8, False)
|
||||
if decoded is None or len(decoded) < 2 or len(decoded) > 40:
|
||||
return (None, None)
|
||||
if data[0] > 16:
|
||||
return (None, None)
|
||||
if data[0] == 0 and len(decoded) != 20 and len(decoded) != 32:
|
||||
return (None, None)
|
||||
if data[0] == 0 and spec != Encoding.BECH32 or data[0] != 0 and spec != Encoding.BECH32M:
|
||||
return (None, None)
|
||||
return (data[0], decoded)
|
||||
|
||||
|
||||
def encode(hrp, witver, witprog):
|
||||
"""Encode a segwit address."""
|
||||
spec = Encoding.BECH32 if witver == 0 else Encoding.BECH32M
|
||||
ret = bech32_encode(hrp, [witver] + convertbits(witprog, 8, 5), spec)
|
||||
if decode(hrp, ret) == (None, None):
|
||||
return None
|
||||
return ret
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
import socket
|
||||
from typing import Union
|
||||
from urllib.parse import urlparse
|
||||
from ipaddress import ip_address, ip_network, IPv4Address
|
||||
|
||||
class UrlValidator:
|
||||
@staticmethod
|
||||
def is_internal_address(ip: Union[IPv4Address]) -> bool:
|
||||
return any([
|
||||
ip.is_private,
|
||||
ip.is_unspecified,
|
||||
ip.is_reserved,
|
||||
ip.is_loopback,
|
||||
ip.is_multicast,
|
||||
ip.is_link_local,
|
||||
])
|
||||
|
||||
@classmethod
|
||||
def validate(cls, url: str):
|
||||
DEFAULT_PORT_WHITELIST = {80, 81, 8080, 443, 8443, 8000}
|
||||
DEFAULT_SCHEME_WHITELIST = {'http', 'https'}
|
||||
DEFAULT_HOST_BLACKLIST = {'192.0.0.192', '169.254.169.254', '100.100.100.200', 'metadata.packet.net', 'metadata.google.internal'}
|
||||
DEFAULT_CHARACTER_WHITELIST = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:/-_.?&='
|
||||
|
||||
if url is None:
|
||||
return False
|
||||
|
||||
whitelist_set = set(DEFAULT_CHARACTER_WHITELIST)
|
||||
if any(c not in whitelist_set for c in url):
|
||||
return False
|
||||
|
||||
try:
|
||||
ip = ip_address(url)
|
||||
except ValueError:
|
||||
try:
|
||||
host = urlparse(url).hostname
|
||||
ip = ip_address(str(socket.gethostbyname(host)))
|
||||
except:
|
||||
return False
|
||||
|
||||
port_whitelist = DEFAULT_PORT_WHITELIST.copy()
|
||||
scheme_whitelist = DEFAULT_SCHEME_WHITELIST.copy()
|
||||
host_blacklist = DEFAULT_HOST_BLACKLIST.copy()
|
||||
|
||||
try:
|
||||
port, scheme = urlparse(url).port, urlparse(url).scheme
|
||||
except:
|
||||
return False
|
||||
|
||||
if scheme_whitelist and scheme is not None and scheme not in scheme_whitelist:
|
||||
return False
|
||||
|
||||
if host_blacklist and host is not None and host in host_blacklist:
|
||||
return False
|
||||
|
||||
if port_whitelist and port is not None and port not in port_whitelist:
|
||||
return False
|
||||
|
||||
if ip.version == 4:
|
||||
if not ip.is_private:
|
||||
# CGNAT IPs do not set `is_private` so `not is_global` added
|
||||
if not ip_network(ip).is_global:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
|
||||
if cls.is_internal_address(ip):
|
||||
return False
|
||||
|
||||
return True
|
|
@ -1,18 +1,5 @@
|
|||
from django import forms
|
||||
from django.forms import ModelForm
|
||||
from users.models import User
|
||||
from .models import VendorsData, VendorsAddresses, InvoiceCreation, ApiPaymentCreation
|
||||
from django.contrib.auth.forms import SetPasswordForm, PasswordResetForm
|
||||
|
||||
class InvoiceCreationForm(ModelForm):
|
||||
class Meta:
|
||||
model = InvoiceCreation
|
||||
fields = ['invoiceID', 'invoiceAmount', 'invoiceCoin', 'invoiceCallbackLink', 'invoiceReturnLink', 'invoiceCoin']
|
||||
|
||||
class ApiPaymentCreationForm(ModelForm):
|
||||
class Meta:
|
||||
model = ApiPaymentCreation
|
||||
fields = ['userUUID', 'usercallbackUrl','userIP','userCoin','statusFlag','paidFlag','ourAddr']
|
||||
from .models import VendorsData, VendorsAddresses
|
||||
|
||||
class VendorEditForm(ModelForm):
|
||||
class Meta:
|
||||
|
@ -22,41 +9,4 @@ class VendorEditForm(ModelForm):
|
|||
class VendorAddrAddForm(ModelForm):
|
||||
class Meta:
|
||||
model = VendorsAddresses
|
||||
fields = ['coin', 'address']
|
||||
|
||||
class UserRegistrationForm(ModelForm):
|
||||
MIN_LENGTH = 8
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ['first_name', 'last_name', 'email', 'password']
|
||||
|
||||
def clean_email(self):
|
||||
email = self.cleaned_data.get('email')
|
||||
if User.objects.filter(email=email).exists():
|
||||
raise forms.ValidationError('Email used, try reseting the password if thats you.')
|
||||
return email
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
password = cleaned_data.get('password')
|
||||
if len(password) < self.MIN_LENGTH:
|
||||
raise forms.ValidationError('The password you are trying to use is too short')
|
||||
|
||||
|
||||
class SetPasswordForm(SetPasswordForm):
|
||||
class Meta:
|
||||
model = User()
|
||||
fields = ['new_password1', 'new_password2']
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
password = cleaned_data.get('new_password1')
|
||||
password2 = cleaned_data.get('new_password2')
|
||||
|
||||
class PasswordResetForm(PasswordResetForm):
|
||||
class Meta:
|
||||
model = User()
|
||||
fields = ['email']
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(PasswordResetForm, self).__init__(*args, **kwargs)
|
||||
fields = ['coin', 'address']
|
|
@ -1,78 +1,14 @@
|
|||
import string, hashlib, binascii, random, socket, base58, sys, requests, json
|
||||
from requests.auth import HTTPDigestAuth
|
||||
import string, hashlib, binascii, random, socket, base58, sys
|
||||
from typing import Union
|
||||
from urllib.parse import urlparse
|
||||
from ipaddress import ip_address, ip_network, IPv4Address
|
||||
from base58 import b58decode_check, b58encode_check
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class RPCHost(object):
|
||||
def __init__(self, url):
|
||||
self._session = requests.Session()
|
||||
self._url = url
|
||||
self._headers = {'content-type': 'application/json'}
|
||||
def call(self, rpcMethod, *params):
|
||||
payload = json.dumps({"method": rpcMethod, "params": list(params), "jsonrpc": "2.0"})
|
||||
tries = 3
|
||||
hadConnectionFailures = False
|
||||
while True:
|
||||
try:
|
||||
response = self._session.post(self._url, headers=self._headers, data=payload, timeout=15)
|
||||
except requests.exceptions.ConnectionError:
|
||||
tries -= 1
|
||||
if tries == 0:
|
||||
raise Exception('Failed to connect for remote procedure call.')
|
||||
hadFailedConnections = True
|
||||
print("Couldn't connect for remote procedure call, will sleep for two seconds and then try again ({} more tries)".format(tries))
|
||||
#time.sleep(2)
|
||||
else:
|
||||
if hadConnectionFailures:
|
||||
print('Connected for remote procedure call after retry.')
|
||||
break
|
||||
if not response.status_code in (200, 500):
|
||||
raise Exception('RPC connection failure: ' + str(response.status_code) + ' ' + response.reason)
|
||||
responseJSON = response.json()
|
||||
if 'error' in responseJSON and responseJSON['error'] != None:
|
||||
raise Exception('Error in RPC call: ' + str(responseJSON['error']))
|
||||
return responseJSON['result']
|
||||
|
||||
class RPCXMR(object):
|
||||
def __init__(self, url, user, password):
|
||||
self._session = requests.Session()
|
||||
self._url = url
|
||||
self._user = user
|
||||
self._pass = password
|
||||
self._headers = {}
|
||||
|
||||
def call(self, rpcMethod, params):
|
||||
payload = json.dumps({"method": rpcMethod, "params": params, "jsonrpc": "2.0"})
|
||||
tries = 3
|
||||
hadConnectionFailures = False
|
||||
while True:
|
||||
try:
|
||||
response = self._session.post(self._url, headers=self._headers, data=payload, auth=HTTPDigestAuth(self._user, self._pass), timeout=15)
|
||||
except requests.exceptions.ConnectionError:
|
||||
tries -= 1
|
||||
if tries == 0:
|
||||
raise Exception('Failed to connect for remote procedure call.')
|
||||
hadFailedConnections = True
|
||||
print("Couldn't connect for remote procedure call, will sleep for two seconds and then try again ({} more tries)".format(tries))
|
||||
#time.sleep(2)
|
||||
else:
|
||||
if hadConnectionFailures:
|
||||
print('Connected for remote procedure call after retry.')
|
||||
break
|
||||
if not response.status_code in (200, 500):
|
||||
raise Exception('RPC connection failure: ' + str(response.status_code) + ' ' + response.reason)
|
||||
responseJSON = response.json()
|
||||
if 'error' in responseJSON and responseJSON['error'] != None:
|
||||
raise Exception('Error in RPC call: ' + str(responseJSON['error']))
|
||||
return responseJSON['result']
|
||||
|
||||
def vendor_generator(size=6, chars=string.ascii_uppercase + string.digits):
|
||||
return ''.join(random.choice(chars) for _ in range(size))
|
||||
|
||||
|
||||
def decodeBase58(address):
|
||||
decoded = base58.b58decode(address).hex()
|
||||
prefixAndHash = decoded[:len(decoded)-8]
|
||||
|
@ -102,17 +38,15 @@ def decodeMonero(address):
|
|||
def checksumCheck(method, address):
|
||||
match method.lower():
|
||||
case 'btc':
|
||||
return decodeBase58(address) if address[0] == '1' or address[0] == '3' else True if address[0:3] == 'bc1' and bdecode("bc", address)[0] != None else False
|
||||
return decodeBase58(address) if address[0] == '1' or address[0] == '3' else True if address[0:3] == 'bc1' and decode("bc", address)[0] != None else False
|
||||
case 'btct':
|
||||
return decodeBase58(address) if address[0] == '2' else True if address[0:3] == 'tb1' and bdecode("tb", address)[0] != None else False
|
||||
return decodeBase58(address) if address[0] == '2' else True if address[0:3] == 'tb1' and decode("tb", address)[0] != None else False
|
||||
case 'ltc':
|
||||
return decodeBase58(address) if address[0] == '3' or address[0] == 'M' or address[0] == 'L' else True if address[0:4] == 'ltc1' and bdecode("ltc", address)[0] != None else False
|
||||
return decodeBase58(address) if address[0] == '3' or address[0] == 'M' or address[0] == 'L' else True if address[0:4] == 'ltc1' and decode("ltc", address)[0] != None else False
|
||||
case 'bch':
|
||||
return is_valid(address) if address[0] == '1' else True if is_valid('bitcoincash:'+address) == True else False
|
||||
case 'zec':
|
||||
return decodeBase58(address) if address[0] == 't' or address[0] == 'z' else False
|
||||
case 'doge':
|
||||
return decodeBase58(address)
|
||||
case 'xmr':
|
||||
#needs new function to check if address is valid, a decoder maybe
|
||||
return decodeMonero(address)
|
||||
|
@ -283,7 +217,7 @@ def convertbits(data, frombits, tobits, pad=True):
|
|||
return ret
|
||||
|
||||
|
||||
def bdecode(hrp, addr):
|
||||
def decode(hrp, addr):
|
||||
"""Decode a segwit address."""
|
||||
hrpgot, data, spec = bech32_decode(addr)
|
||||
if hrpgot != hrp:
|
||||
|
@ -300,11 +234,11 @@ def bdecode(hrp, addr):
|
|||
return (data[0], decoded)
|
||||
|
||||
|
||||
def bencode(hrp, witver, witprog):
|
||||
def encode(hrp, witver, witprog):
|
||||
"""Encode a segwit address."""
|
||||
spec = Encoding.BECH32 if witver == 0 else Encoding.BECH32M
|
||||
ret = bech32_encode(hrp, [witver] + convertbits(witprog, 8, 5), spec)
|
||||
if bdecode(hrp, ret) == (None, None):
|
||||
if decode(hrp, ret) == (None, None):
|
||||
return None
|
||||
return ret
|
||||
|
||||
|
@ -692,4 +626,4 @@ def decode(enc):
|
|||
return _binToHex(data)
|
||||
|
||||
#########################################################################
|
||||
#########################################################################
|
||||
#########################################################################
|
|
@ -1,31 +0,0 @@
|
|||
# Generated by Django 4.2 on 2023-05-17 10:57
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('base', '0009_alter_vendorsdata_id'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='CryptoCoins',
|
||||
fields=[
|
||||
('id', models.BigAutoField(primary_key=True, serialize=False)),
|
||||
('coinName', models.CharField(max_length=250)),
|
||||
('coinSymbol', models.CharField(max_length=10)),
|
||||
('coinIsActive', models.BooleanField(default=True)),
|
||||
('coinAddDate', models.DateTimeField(auto_now_add=True)),
|
||||
('coinUpdated', models.DateTimeField(auto_now=True)),
|
||||
('coinDelete', models.DateTimeField(auto_now_add=True)),
|
||||
('coinDeleted', models.BooleanField(default=False)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Crypto Coin',
|
||||
'verbose_name_plural': 'Crypto Coins',
|
||||
'ordering': ['-id'],
|
||||
},
|
||||
),
|
||||
]
|
|
@ -1,38 +0,0 @@
|
|||
# Generated by Django 4.2 on 2023-05-17 11:25
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('base', '0010_cryptocoins'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='cryptocoins',
|
||||
name='coinDelete',
|
||||
field=models.DateTimeField(blank=True),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='VendorsAddresses',
|
||||
fields=[
|
||||
('id', models.BigAutoField(primary_key=True, serialize=False)),
|
||||
('vendorUUID', models.UUIDField()),
|
||||
('address', models.CharField(max_length=250)),
|
||||
('addrAddDate', models.DateTimeField(auto_now_add=True)),
|
||||
('addrDeleted', models.BooleanField(default=False)),
|
||||
('addrUpdated', models.DateTimeField(auto_now=True)),
|
||||
('addrIsActive', models.BooleanField(default=True)),
|
||||
('Coin', models.ManyToManyField(to='base.cryptocoins')),
|
||||
('vendor', models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='base.vendorsdata')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Vendor',
|
||||
'verbose_name_plural': 'Vendors',
|
||||
'ordering': ['-id'],
|
||||
},
|
||||
),
|
||||
]
|
|
@ -1,17 +0,0 @@
|
|||
# Generated by Django 4.2 on 2023-05-17 11:26
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('base', '0011_alter_cryptocoins_coindelete_vendorsaddresses'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='vendorsaddresses',
|
||||
options={'ordering': ['-id'], 'verbose_name': 'Address', 'verbose_name_plural': 'Addresses'},
|
||||
),
|
||||
]
|
|
@ -1,22 +0,0 @@
|
|||
# Generated by Django 4.2 on 2023-05-17 11:28
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('base', '0012_alter_vendorsaddresses_options'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='vendorsaddresses',
|
||||
name='Coin',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='vendorsaddresses',
|
||||
name='Coin',
|
||||
field=models.IntegerField(default=0),
|
||||
),
|
||||
]
|
|
@ -1,18 +0,0 @@
|
|||
# Generated by Django 4.2 on 2023-05-17 11:31
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('base', '0013_remove_vendorsaddresses_coin_vendorsaddresses_coin'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='cryptocoins',
|
||||
name='coinDelete',
|
||||
field=models.DateTimeField(blank=True, null=True),
|
||||
),
|
||||
]
|
|
@ -1,18 +0,0 @@
|
|||
# Generated by Django 4.2 on 2023-05-18 09:22
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('base', '0014_alter_cryptocoins_coindelete'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='cryptocoins',
|
||||
name='coinDelete',
|
||||
field=models.DateTimeField(auto_now_add=True, null=True),
|
||||
),
|
||||
]
|
|
@ -1,23 +0,0 @@
|
|||
# Generated by Django 4.2 on 2023-05-18 12:42
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('base', '0015_alter_cryptocoins_coindelete'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='vendorsaddresses',
|
||||
old_name='Coin',
|
||||
new_name='coin',
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='vendorsdata',
|
||||
name='vendorSecretKey',
|
||||
field=models.CharField(max_length=250),
|
||||
),
|
||||
]
|
|
@ -1,22 +0,0 @@
|
|||
# Generated by Django 4.2 on 2023-05-19 12:15
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('base', '0016_rename_coin_vendorsaddresses_coin_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='vendorsaddresses',
|
||||
options={'ordering': ['id'], 'verbose_name': 'Address', 'verbose_name_plural': 'Addresses'},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='vendorsaddresses',
|
||||
name='coin',
|
||||
field=models.CharField(max_length=10),
|
||||
),
|
||||
]
|
|
@ -1,25 +0,0 @@
|
|||
# Generated by Django 4.2 on 2023-05-21 10:19
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('base', '0017_alter_vendorsaddresses_options_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='vendorsaddresses',
|
||||
options={'ordering': ['-addrIsActive'], 'verbose_name': 'Address', 'verbose_name_plural': 'Addresses'},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='vendorsaddresses',
|
||||
name='vendorid',
|
||||
field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
|
@ -1,21 +0,0 @@
|
|||
# Generated by Django 4.2 on 2023-05-21 10:20
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('base', '0018_alter_vendorsaddresses_options_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='vendorsaddresses',
|
||||
name='vendorid',
|
||||
field=models.ForeignKey(default=0, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
|
@ -1,21 +0,0 @@
|
|||
# Generated by Django 4.2 on 2023-05-21 10:21
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('base', '0019_alter_vendorsaddresses_vendorid'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='vendorsaddresses',
|
||||
name='vendorid',
|
||||
field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
|
@ -1,21 +0,0 @@
|
|||
# Generated by Django 4.2 on 2023-05-21 10:22
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('base', '0020_alter_vendorsaddresses_vendorid'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='vendorsaddresses',
|
||||
name='vendorid',
|
||||
field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
|
@ -1,22 +0,0 @@
|
|||
# Generated by Django 4.2 on 2023-05-29 11:45
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('base', '0021_alter_vendorsaddresses_vendorid'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='vendorsaddresses',
|
||||
options={'ordering': ['-addrAddDate'], 'verbose_name': 'Address', 'verbose_name_plural': 'Addresses'},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='vendorsdata',
|
||||
name='vendorNetworkFee',
|
||||
field=models.IntegerField(default=0),
|
||||
),
|
||||
]
|
|
@ -1,42 +0,0 @@
|
|||
# Generated by Django 4.2 on 2023-07-06 08:37
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('base', '0022_alter_vendorsaddresses_options_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='InvoiceCreation',
|
||||
fields=[
|
||||
('id', models.BigAutoField(primary_key=True, serialize=False)),
|
||||
('invoiceUUID', models.UUIDField()),
|
||||
('invoiceID', models.CharField(max_length=255)),
|
||||
('invoiceAmount', models.DecimalField(decimal_places=2, max_digits=20)),
|
||||
('invoiceCoin', models.CharField(max_length=10)),
|
||||
('invoiceState', models.IntegerField(default=0)),
|
||||
('invoiceBuyerEmail', models.CharField(max_length=255)),
|
||||
('invoiceCallbackLink', models.CharField(max_length=1000)),
|
||||
('invoiceReturnLink', models.CharField(max_length=1000)),
|
||||
('invoiceDeleteLink', models.CharField(max_length=1000)),
|
||||
('invoiceDeleted', models.BooleanField(default=False)),
|
||||
('invoiceAddDate', models.DateTimeField(auto_now_add=True)),
|
||||
('invoiceUpdateDate', models.DateTimeField(auto_now=True)),
|
||||
('invoiceDeleteDate', models.DateTimeField(blank=True, null=True)),
|
||||
('invoiceVendor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='base.vendorsdata')),
|
||||
('invoiceVendorid', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Invoice',
|
||||
'verbose_name_plural': 'Invoices',
|
||||
'ordering': ['-invoiceAddDate'],
|
||||
},
|
||||
),
|
||||
]
|
|
@ -1,18 +0,0 @@
|
|||
# Generated by Django 4.2 on 2023-07-07 13:12
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('base', '0023_invoicecreation'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='invoicecreation',
|
||||
name='invoiceBuyerEmail',
|
||||
field=models.CharField(max_length=255, null=True),
|
||||
),
|
||||
]
|
|
@ -1,18 +0,0 @@
|
|||
# Generated by Django 4.2 on 2023-07-07 13:16
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('base', '0024_alter_invoicecreation_invoicebuyeremail'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='invoicecreation',
|
||||
name='invoiceCoin',
|
||||
field=models.CharField(default='USD', max_length=10),
|
||||
),
|
||||
]
|
|
@ -1,28 +0,0 @@
|
|||
# Generated by Django 4.2 on 2023-07-07 14:49
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('base', '0025_alter_invoicecreation_invoicecoin'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='invoicecreation',
|
||||
name='invoiceCallbackLink',
|
||||
field=models.URLField(max_length=1000),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='invoicecreation',
|
||||
name='invoiceDeleteLink',
|
||||
field=models.URLField(max_length=1000),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='invoicecreation',
|
||||
name='invoiceReturnLink',
|
||||
field=models.URLField(max_length=1000),
|
||||
),
|
||||
]
|
|
@ -1,18 +0,0 @@
|
|||
# Generated by Django 4.2 on 2023-07-07 14:50
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('base', '0026_alter_invoicecreation_invoicecallbacklink_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='invoicecreation',
|
||||
name='invoiceBuyerEmail',
|
||||
field=models.EmailField(max_length=255, null=True),
|
||||
),
|
||||
]
|
|
@ -1,19 +0,0 @@
|
|||
# Generated by Django 4.2 on 2023-07-08 11:35
|
||||
|
||||
import base.models
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('base', '0027_alter_invoicecreation_invoicebuyeremail'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='invoicecreation',
|
||||
name='invoiceCoin',
|
||||
field=models.CharField(default=base.models.InvoiceCreation.default_currency, max_length=10),
|
||||
),
|
||||
]
|
|
@ -1,18 +0,0 @@
|
|||
# Generated by Django 4.2 on 2023-07-08 11:52
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('base', '0028_alter_invoicecreation_invoicecoin'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='invoicecreation',
|
||||
name='invoiceDeleteLink',
|
||||
field=models.URLField(max_length=1000, null=True),
|
||||
),
|
||||
]
|
|
@ -1,18 +0,0 @@
|
|||
# Generated by Django 4.2 on 2023-07-08 12:21
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('base', '0029_alter_invoicecreation_invoicedeletelink'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='invoicecreation',
|
||||
name='invoiceUUID',
|
||||
field=models.UUIDField(unique=True),
|
||||
),
|
||||
]
|
|
@ -1,44 +0,0 @@
|
|||
# Generated by Django 4.2 on 2023-08-08 09:47
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('base', '0030_alter_invoicecreation_invoiceuuid'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ApiPaymentCreation',
|
||||
fields=[
|
||||
('id', models.BigAutoField(primary_key=True, serialize=False)),
|
||||
('userAddr', models.CharField(max_length=255)),
|
||||
('userUUID', models.UUIDField()),
|
||||
('userCoin', models.CharField(max_length=10)),
|
||||
('userAmount', models.DecimalField(decimal_places=2, max_digits=20)),
|
||||
('usercallbackUrl', models.URLField(max_length=1000, null=True)),
|
||||
('userIP', models.GenericIPAddressField()),
|
||||
('ourAddr', models.CharField(max_length=255)),
|
||||
('statusFlag', models.IntegerField(default=0)),
|
||||
('paidFlag', models.IntegerField(default=0)),
|
||||
('created', models.DateTimeField(auto_now_add=True)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'ApiInvoice',
|
||||
'verbose_name_plural': 'ApiInvoices',
|
||||
'ordering': ['-id'],
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='cryptocoins',
|
||||
name='coinAPI',
|
||||
field=models.BooleanField(default=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='cryptocoins',
|
||||
name='coinMerch',
|
||||
field=models.BooleanField(default=True),
|
||||
),
|
||||
]
|
|
@ -9,8 +9,6 @@ class CryptoCoins(models.Model):
|
|||
id = models.BigAutoField(primary_key=True)
|
||||
coinName = models.CharField(max_length=250)
|
||||
coinSymbol = models.CharField(max_length=10)
|
||||
coinAPI = models.BooleanField(default=True)
|
||||
coinMerch = models.BooleanField(default=True)
|
||||
coinIsActive = models.BooleanField(default=True)
|
||||
coinAddDate = models.DateTimeField(auto_now_add=True)
|
||||
coinUpdated = models.DateTimeField(auto_now=True)
|
||||
|
@ -66,9 +64,6 @@ class VendorsAddresses(models.Model):
|
|||
|
||||
def __str__(self):
|
||||
return self.address
|
||||
|
||||
def __repr__(self):
|
||||
return self._repr()
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Address"
|
||||
|
@ -76,57 +71,4 @@ class VendorsAddresses(models.Model):
|
|||
ordering = ["-addrAddDate"]
|
||||
|
||||
|
||||
class InvoiceCreation(models.Model):
|
||||
|
||||
def default_currency():
|
||||
return 'USD'
|
||||
|
||||
id = models.BigAutoField(primary_key=True)
|
||||
invoiceVendor = models.ForeignKey(VendorsData, on_delete=models.CASCADE)
|
||||
invoiceVendorid = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
invoiceUUID = models.UUIDField(unique=True)
|
||||
invoiceID = models.CharField(max_length=255)
|
||||
invoiceAmount = models.DecimalField(max_digits=20, decimal_places=2)
|
||||
invoiceCoin = models.CharField(max_length=10, default=default_currency, null=False)
|
||||
invoiceState = models.IntegerField(default=0)
|
||||
invoiceBuyerEmail = models.EmailField(max_length=255, null=True)
|
||||
invoiceCallbackLink = models.URLField(max_length=1000)
|
||||
invoiceReturnLink = models.URLField(max_length=1000)
|
||||
invoiceDeleteLink = models.URLField(max_length=1000, null=True)
|
||||
invoiceDeleted = models.BooleanField(default=False)
|
||||
invoiceAddDate = models.DateTimeField(auto_now_add=True)
|
||||
invoiceUpdateDate = models.DateTimeField(auto_now=True)
|
||||
invoiceDeleteDate = models.DateTimeField(blank=True, null=True)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.invoiceUUID)
|
||||
|
||||
def __repr__(self):
|
||||
return self._repr()
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Invoice"
|
||||
verbose_name_plural = "Invoices"
|
||||
ordering = ["-invoiceAddDate"]
|
||||
|
||||
|
||||
class ApiPaymentCreation(models.Model):
|
||||
id = models.BigAutoField(primary_key=True)
|
||||
userAddr = models.CharField(max_length=255)
|
||||
userUUID = models.UUIDField()
|
||||
userCoin = models.CharField(max_length=10)
|
||||
userAmount = models.DecimalField(max_digits=20, decimal_places=2)
|
||||
usercallbackUrl = models.URLField(max_length=1000, null=True)
|
||||
userIP = models.GenericIPAddressField()
|
||||
ourAddr = models.CharField(max_length=255)
|
||||
statusFlag = models.IntegerField(default=0)
|
||||
paidFlag = models.IntegerField(default=0)
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.ourAddr)
|
||||
|
||||
class Meta:
|
||||
verbose_name = "ApiInvoice"
|
||||
verbose_name_plural = "ApiInvoices"
|
||||
ordering = ["-id"]
|
47
base/rpcs.py
|
@ -1,47 +0,0 @@
|
|||
## DAEMONS ##
|
||||
# BTC
|
||||
rpcs = {
|
||||
'BTC': {
|
||||
'host': '172.16.0.2',
|
||||
'port': 8332,
|
||||
'user': '55c44311a1e1708ec1afbf9949c96d08',
|
||||
'pass': 'lzD8NH4sexdTHnRJ1BxZfBvUxZHlvmW2bwDsF'
|
||||
},
|
||||
'BTCT': {
|
||||
'host': '172.16.2.2',
|
||||
'port': 18332,
|
||||
'user': '55c44311a1e1708ec1afbf9949c96d08',
|
||||
'pass': 'lzD8NH4sexdTHnRJ1BxZfBvUxZHlvmW2bwDsF'
|
||||
},
|
||||
'LTC': {
|
||||
'host': '172.16.1.2',
|
||||
'port': 9332,
|
||||
'user': '55c44311a1e1708ec1afbf9949c96d08',
|
||||
'pass': 'lzD8NH4sexdTHnRJ1BxZfBvUxZHlvmW2bwDsF'
|
||||
},
|
||||
'BCH': {
|
||||
'host': '172.16.3.2',
|
||||
'port': 8552,
|
||||
'user': '55c44311a1e1708ec1afbf9949c96d08',
|
||||
'pass': 'lzD8NH4sexdTHnRJ1BxZfBvUxZHlvmW2bwDsF'
|
||||
},
|
||||
'ZEC': {
|
||||
'host': '172.16.5.2',
|
||||
'port': 8552,
|
||||
'user': '55c44311a1e1708ec1afbf9949c96d08',
|
||||
'pass': 'lzD8NH4sexdTHnRJ1BxZfBvUxZHlvmW2bwDsF'
|
||||
},
|
||||
'DOGE': {
|
||||
'host': '172.16.6.2',
|
||||
'port': 25555,
|
||||
'user': '55c44311a1e1708ec1afbf9949c96d08',
|
||||
'pass': 'lzD8NH4sexdTHnRJ1BxZfBvUxZHlvmW2bwDsF'
|
||||
},
|
||||
'XMR': {
|
||||
'host': 'http://172.16.4.3:18083/json_rpc',
|
||||
'user': '55c44311a1e1708ec1afbf9949c96d08',
|
||||
'pass': 'lzD8NH4sexdTHnRJ1BxZfBvUxZHlvmW2bwDsF'
|
||||
},
|
||||
}
|
||||
|
||||
API_FEE = 0.02
|
0
base/templates/base/lp_dashboard.html → base/templates/base/dashboard.html
Executable file → Normal file
|
@ -1,20 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Square with Bitcoin Image and Text</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="outer-square">
|
||||
<div class="inner-square">
|
||||
<img class="image" src="https://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bitcoin.svg/800px-Bitcoin.svg.png" alt="Bitcoin Logo" width="50" height="50">
|
||||
<div class="crypto-info">
|
||||
<h1>Bitcoin</h1>
|
||||
<p>BTC</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,83 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" class="h-100">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title> </title>
|
||||
<meta name="robots" content="index">
|
||||
<meta name="description" content="">
|
||||
<meta name="keywords" content="">
|
||||
<meta name="author" content="LitePay.ch">
|
||||
|
||||
<!-- Favicon icon -->
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="https://ik.imagekit.io/litepaych/assets/dashboard/images/logo_litepay_2020_white_box.png">
|
||||
<link href="https://litepay.ch//assets/new/secure/css/style.css" rel="stylesheet">
|
||||
<link rel="canonical" href="https://litepay.ch/merchant/login">
|
||||
|
||||
</head>
|
||||
|
||||
|
||||
{% block content %}
|
||||
<!-- ============================================================== -->
|
||||
<!-- Start right Content here -->
|
||||
<!-- ============================================================== -->
|
||||
<!-- Main content -->
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="https://ik.imagekit.io/litepaych/assets/dashboard/images/logo_litepay_2020_white_box.png">
|
||||
<h1 style="visibility: hidden"> Sign in your Litepay.ch account </h1>
|
||||
<body class="h-100">
|
||||
<div class="authincation h-100">
|
||||
<div class="container h-100">
|
||||
<div class="row justify-content-center h-100 align-items-center">
|
||||
<div class="col-md-6">
|
||||
<div class="authincation-content">
|
||||
<div class="row no-gutters">
|
||||
<div class="col-xl-12">
|
||||
<div class="auth-form">
|
||||
<img style="display: block; margin-left: auto; margin-right: auto; width: 50%; padding-bottom: 2px" src="https://ik.imagekit.io/litepaych/assets/new/img/logo_litepay_2020_blue.png" alt="Litepay.ch Merchant"></a>
|
||||
<h2 class="text-center mb-4">Sign in</h2>
|
||||
<form action="" method="POST">
|
||||
{% csrf_token %}
|
||||
<div class="form-group">
|
||||
<label class="mb-1"><strong>Email</strong></label>
|
||||
<input type="email" class="form-control" name="email" value="Email">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="mb-1"><strong>Password</strong></label>
|
||||
<input type="password" class="form-control" name="password" value="Password">
|
||||
</div>
|
||||
<div class="form-row d-flex justify-content-between mt-4 mb-2">
|
||||
<div class="form-group">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<a href="/merchant/forgot-password">Forgot Password?</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<button type="submit" class="btn btn-primary btn-block">Sign Me In</button>
|
||||
</div>
|
||||
</form>
|
||||
<div class="new-account mt-3">
|
||||
<p>Don't have an account? <a class="text-primary" href="/merchant/register">Sign up</a></p>
|
||||
</div>
|
||||
</div>
|
||||
{% if messages %}
|
||||
<ul class="messages text-center">
|
||||
{% for message in messages %}
|
||||
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<!-- end main content-->
|
||||
{% endblock content %}
|
||||
</html>
|
|
@ -1,136 +0,0 @@
|
|||
{% load static %}
|
||||
<!doctype html>
|
||||
<html lang="en" data-theme="light">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||
<meta name="color-scheme" content="dark light">
|
||||
<title>Satoshi - DeFi and Crypto Exchange Theme</title>
|
||||
<!-- Styles -->
|
||||
<link rel="stylesheet" type="text/css" href="{% static '/css/main.css'%}">
|
||||
<link rel="stylesheet" type="text/css" href="{% static '/css/utility.css'%}">
|
||||
<!-- Bootstrap Icons -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.2/font/bootstrap-icons.css">
|
||||
<!-- Fonts -->
|
||||
<link rel="stylesheet" href="https://api.fontshare.com/v2/css?f=satoshi@900,700,500,300,401,400&display=swap">
|
||||
</head>
|
||||
|
||||
<body class="bg-surface-secondary">
|
||||
|
||||
<div class="d-flex flex-column flex-lg-row h-lg-full">
|
||||
|
||||
<div class="flex-lg-fill overflow-x-auto vstack h-lg-screen">
|
||||
|
||||
<div class="flex-fill overflow-y-lg-auto scrollbar bg-surface-primary rounded-top-4 rounded-top-start-lg-4 rounded-top-end-lg-0 border-top border-lg shadow">
|
||||
<main class="container-fluid px-3 py-5 p-lg-6 p-xxl-10">
|
||||
<div class="modal fade show" id="cryptoModal" tabindex="-1" aria-labelledby="cryptoModalLabel" style="display: block" aria-modal="true" role="dialog">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="row g-3 g-xxl-6">
|
||||
<div class="col-xxl-12">
|
||||
<div class="vstack gap-3 gap-md-6">
|
||||
<div class="row g-3">
|
||||
<div class="col-md col-sm-6">
|
||||
<div class="card bg-success bg-opacity-10 border-success border-opacity-40">
|
||||
<div class="card-body p-4">
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<img class="w-5 flex-none" src="{% static '/img/crypto/color/usdt.svg' %}" alt="..." />
|
||||
<h6>USDT</h6>
|
||||
</div>
|
||||
<div class="text-xs mt-4">
|
||||
Total balance
|
||||
</div>
|
||||
<div class="text-sm font-semibold">
|
||||
75.800,00 USDT
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md col-sm-6">
|
||||
<div class="card border-primary-hover">
|
||||
<div class="card-body p-4">
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<img class="w-5 flex-none" src="{% static '/img/crypto/color/btc.svg' %}" alt="..." />
|
||||
<a href="/pages/exchange-details.html" class="h6 stretched-link">BTC</a>
|
||||
</div>
|
||||
<div class="text-sm font-semibold mt-3">
|
||||
3.2893 USDT
|
||||
</div>
|
||||
<div class="d-flex align-items-center gap-2 mt-1 text-xs">
|
||||
<span class="badge badge-xs rounded-pill text-bg-success">
|
||||
<i class="bi bi-arrow-up-right"></i>
|
||||
</span>
|
||||
<span>+13.7%</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md col-sm-6">
|
||||
<div class="card border-primary-hover">
|
||||
<div class="card-body p-4">
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<img class="w-5 flex-none" src="{% static '/img/crypto/color/ada.svg' %}" alt="..." />
|
||||
<a href="/pages/exchange-details.html" class="h6 stretched-link">ADA</a>
|
||||
</div>
|
||||
<div class="text-sm font-semibold mt-3">
|
||||
10.745,49 ADA
|
||||
</div>
|
||||
<div class="d-flex align-items-center gap-2 mt-1 text-xs">
|
||||
<span class="badge badge-xs rounded-pill text-bg-danger">
|
||||
<i class="bi bi-arrow-up-right"></i>
|
||||
</span>
|
||||
<span>-3.2%</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md col-sm-6">
|
||||
<div class="card border-primary-hover">
|
||||
<div class="card-body p-4">
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<img class="w-5 flex-none" src="{% static '/img/crypto/color/eos.svg' %}" alt="..." />
|
||||
<a href="/pages/exchange-details.html" class="h6 stretched-link">EOS</a>
|
||||
</div>
|
||||
<div class="text-sm font-semibold mt-3">
|
||||
7.890,00 EOS
|
||||
</div>
|
||||
<div class="d-flex align-items-center gap-2 mt-1 text-xs">
|
||||
<span class="badge badge-xs rounded-pill text-bg-danger">
|
||||
<i class="bi bi-arrow-up-right"></i>
|
||||
</span>
|
||||
<span>-2.2%</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,128 +0,0 @@
|
|||
{% load static %}
|
||||
<!doctype html>
|
||||
<html lang="en" data-theme="light">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||
<meta name="color-scheme" content="dark light">
|
||||
<title>Satoshi - DeFi and Crypto Exchange Theme</title>
|
||||
<!-- Styles -->
|
||||
<link rel="stylesheet" type="text/css" href="{% static '/css/main.css'%}">
|
||||
<link rel="stylesheet" type="text/css" href="{% static '/css/utility.css'%}">
|
||||
<!-- Bootstrap Icons -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.2/font/bootstrap-icons.css">
|
||||
<!-- Fonts -->
|
||||
<link rel="stylesheet" href="https://api.fontshare.com/v2/css?f=satoshi@900,700,500,300,401,400&display=swap">
|
||||
</head>
|
||||
|
||||
<body class="bg-surface-secondary">
|
||||
|
||||
<div class="d-flex flex-column flex-lg-row h-lg-full">
|
||||
|
||||
<div class="flex-lg-fill overflow-x-auto vstack h-lg-screen">
|
||||
|
||||
<div class="flex-fill overflow-y-lg-auto scrollbar bg-surface-primary rounded-top-4 rounded-top-start-lg-4 rounded-top-end-lg-0 border-top border-lg shadow">
|
||||
<main class="container-fluid px-3 py-5 p-lg-6 p-xxl-10">
|
||||
<div class="modal fade show" id="cryptoModal" tabindex="-1" aria-labelledby="cryptoModalLabel" style="display: block" aria-modal="true" role="dialog">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
|
||||
|
||||
<div class="modal-content overflow-hidden">
|
||||
<div class="modal-body p-0">
|
||||
<div class="p-2">
|
||||
<div class="vstack">
|
||||
<div class="position-relative d-flex gap-3 p-4 rounded bg-light-hover">
|
||||
<div class="icon flex-none">
|
||||
<img src="{% static '/img/crypto/color/btc.svg' %}" class="w-10 h-10" alt="Pay with Bitcoin" />
|
||||
</div>
|
||||
<div class="d-flex flex-fill">
|
||||
<div class="">
|
||||
<a href="#" class="stretched-link text-heading font-bold">BTC</a>
|
||||
<span class="d-block text-muted text-sm">Bitcoin</span>
|
||||
</div>
|
||||
<div class="ms-auto font-bold text-heading">
|
||||
23.8
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="position-relative d-flex gap-3 p-4 rounded bg-light-hover">
|
||||
<div class="icon flex-none">
|
||||
<img src="{% static '/img/crypto/color/eth.svg' %}" class="w-10 h-10" alt="..." />
|
||||
</div>
|
||||
<div class="d-flex flex-fill">
|
||||
<div class="">
|
||||
<a href="#" class="stretched-link text-heading font-bold">ETH</a>
|
||||
<span class="d-block text-muted text-sm">Ethereum</span>
|
||||
</div>
|
||||
<div class="ms-auto font-bold text-heading">
|
||||
1.200,50
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="position-relative d-flex gap-3 p-4 rounded bg-light-hover">
|
||||
<div class="icon flex-none">
|
||||
<img src="/img/crypto/color/ada.svg" class="w-10 h-10" alt="..." />
|
||||
</div>
|
||||
<div class="d-flex flex-fill">
|
||||
<div class="">
|
||||
<a href="#" class="stretched-link text-heading font-bold">ADA</a>
|
||||
<span class="d-block text-muted text-sm">Cardano</span>
|
||||
</div>
|
||||
<div class="ms-auto font-bold text-heading">
|
||||
10.930,00
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="position-relative d-flex gap-3 p-4 rounded bg-light-hover">
|
||||
<div class="icon flex-none">
|
||||
<img src="/img/crypto/color/bnb.svg" class="w-10 h-10" alt="..." />
|
||||
</div>
|
||||
<div class="d-flex flex-fill">
|
||||
<div class="">
|
||||
<a href="#" class="stretched-link text-heading font-bold">BNB</a>
|
||||
<span class="d-block text-muted text-sm">Binance</span>
|
||||
</div>
|
||||
<div class="ms-auto font-bold text-heading">
|
||||
200
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="position-relative d-flex gap-3 p-4 rounded bg-light-hover">
|
||||
<div class="icon flex-none">
|
||||
<img src="/img/crypto/color/chain.svg" class="w-10 h-10" alt="..." />
|
||||
</div>
|
||||
<div class="d-flex flex-fill">
|
||||
<div class="">
|
||||
<a href="#" class="stretched-link text-heading font-bold">CHAIN</a>
|
||||
<span class="d-block text-muted text-sm">Linkchain</span>
|
||||
</div>
|
||||
<div class="ms-auto font-bold text-heading">
|
||||
200
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="px-6 py-5 bg-light d-flex justify-content-center">
|
||||
<button class="btn btn-sm btn-dark rounded-pill">
|
||||
<i class="bi bi-gear me-2"></i>Manage tokens
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,85 +0,0 @@
|
|||
{% load static %}
|
||||
<!doctype html>
|
||||
<html lang="en" data-theme="light">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||
<meta name="color-scheme" content="light">
|
||||
<title>Satoshi - DeFi and Crypto Exchange Theme</title>
|
||||
<!-- Styles -->
|
||||
<link rel="stylesheet" type="text/css" href="{% static '/css/inv.css'%}">
|
||||
<link rel="stylesheet" type="text/css" href="{% static '/css/styles.css'%}">
|
||||
<link rel="stylesheet" type="text/css" href="{% static '/css/main.css'%}">
|
||||
<link rel="stylesheet" type="text/css" href="{% static '/css/utility.css'%}">
|
||||
|
||||
<!-- Bootstrap Icons -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.2/font/bootstrap-icons.css">
|
||||
<!-- Fonts -->
|
||||
<link rel="stylesheet" href="https://api.fontshare.com/v2/css?f=satoshi@900,700,500,300,401,400&display=swap">
|
||||
</head>
|
||||
|
||||
<body class="bg-surface-secondary">
|
||||
<div class="d-flex flex-column flex-lg-row h-lg-full">
|
||||
|
||||
<div class="flex-lg-fill overflow-x-auto vstack h-lg-screen">
|
||||
|
||||
|
||||
<main class="container-fluid px-3 py-5 p-lg-6 p-xxl-10">
|
||||
<div class="textElements">
|
||||
<img class="mb-6 mt-6 mb-xl-10" src="https://ik.imagekit.io/litepaych/assets/new/img/logo_litepay_2020_blue.png" alt="">
|
||||
<h2 >Invoice #{{invoice.invoiceID}}, {{invoice.invoiceAmount}} {{invoice.invoiceCoin}}</h2>
|
||||
<p>Sold by <a href="{{vendor.vendorWebAddr}}" style="text-decoration: none;">{{vendor.vendorWebName}}</a></p>
|
||||
<p class="mb-6">Feedback: ★★★★★ 100%</p>
|
||||
</div>
|
||||
<div class="containerCrypto">
|
||||
|
||||
<div class="outer-square">
|
||||
|
||||
{% for coin in coins %}
|
||||
<div class="inner-square">
|
||||
<img class="image" src="{% static '/img/crypto/color/'|add:coin.coin|add:'.svg' %}" alt="Bitcoin Logo" width="50" height="50">
|
||||
<div class="crypto-info">
|
||||
<h1>{{coin.coin}}</h1>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="container2">
|
||||
<div class="footer2">
|
||||
<a href="#">
|
||||
<p>Need support?</p>
|
||||
</a>
|
||||
<a href="#">
|
||||
<p>Merchant API</p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</main>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,89 +0,0 @@
|
|||
{% load static %}
|
||||
<!doctype html>
|
||||
<html lang="en" data-theme="light">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||
<meta name="color-scheme" content="light">
|
||||
<title>Satoshi - DeFi and Crypto Exchange Theme</title>
|
||||
<!-- Styles -->
|
||||
<link rel="stylesheet" type="text/css" href="{% static '/css/styles.css'%}">
|
||||
<link rel="stylesheet" type="text/css" href="{% static '/css/main.css'%}">
|
||||
<link rel="stylesheet" type="text/css" href="{% static '/css/utility.css'%}">
|
||||
|
||||
<!-- Bootstrap Icons -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.2/font/bootstrap-icons.css">
|
||||
<!-- Fonts -->
|
||||
<link rel="stylesheet" href="https://api.fontshare.com/v2/css?f=satoshi@900,700,500,300,401,400&display=swap">
|
||||
</head>
|
||||
|
||||
<body class="bg-surface-secondary">
|
||||
<div class="d-flex flex-column flex-lg-row h-lg-full">
|
||||
|
||||
<div class="flex-lg-fill overflow-x-auto vstack h-lg-screen">
|
||||
|
||||
|
||||
<main class="container-fluid px-3 py-5 p-lg-6 p-xxl-10">
|
||||
<div class="modal fade show" id="cryptoModal" tabindex="-1" aria-labelledby="cryptoModalLabel" style="display: block" aria-modal="true" role="dialog">
|
||||
<div class="textElements">
|
||||
<img class="mb-6 mt-6 mb-xl-10" src="https://ik.imagekit.io/litepaych/assets/new/img/logo_litepay_2020_blue.png" alt="">
|
||||
<h2 >Invoice #{{invoice.invoiceID}}, {{invoice.invoiceAmount}} {{invoice.invoiceCoin}}</h2>
|
||||
<p>Sold by <a href="{{vendor.vendorWebAddr}}" style="text-decoration: none;">{{vendor.vendorWebName}}</a></p>
|
||||
<p class="mb-6">Feedback: ★★★★★ 100%</p>
|
||||
</div>
|
||||
<div class="containerCrypto">
|
||||
<div class="selectorContainer" style="padding-left: auto;">
|
||||
{% for coin in coins %}
|
||||
<div class="line" style="padding-bottom: 10px;">
|
||||
<a href="">
|
||||
<div class="crypto">
|
||||
<img src="{% static '/img/crypto/color/'|add:coin.coin|add:'.svg' %}">
|
||||
<div class="crypto-info">
|
||||
<h1>Bitcoin</h1>
|
||||
<p>{{coin.coin}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="container2">
|
||||
<div class="footer2">
|
||||
<a href="#">
|
||||
<p>Need support?</p>
|
||||
</a>
|
||||
<a href="#">
|
||||
<p>Merchant API</p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</main>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,93 +0,0 @@
|
|||
{% load static %}
|
||||
<!doctype html>
|
||||
<html lang="en" data-theme="light">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||
<meta name="color-scheme" content="dark light">
|
||||
<title>{% block title %} {{ title }} {% endblock title %} | Litepay.ch </title>
|
||||
<!-- App favicon -->
|
||||
<link rel="shortcut icon" href="{% static 'images/favicon.ico'%}">
|
||||
{% block css %}
|
||||
<!-- Styles -->
|
||||
<link rel="stylesheet" type="text/css" href="{% static '/css/main.css'%}">
|
||||
<link rel="stylesheet" type="text/css" href="{% static '/css/utility.css'%}">
|
||||
<!-- Bootstrap Icons -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.2/font/bootstrap-icons.css">
|
||||
<!-- Fonts -->
|
||||
<link rel="stylesheet" href="https://api.fontshare.com/v2/css?f=satoshi@900,700,500,300,401,400&display=swap">
|
||||
{% endblock css %}
|
||||
</head>
|
||||
|
||||
|
||||
|
||||
|
||||
<body>
|
||||
<div class="row g-0 justify-content-center gradient-bottom-right start-purple-500 middle-indigo-500 end-pink-500">
|
||||
<div class="col-md-6 col-lg-5 col-xl-5 position-fixed start-0 top-0 h-screen overflow-y-hidden d-none d-lg-flex flex-lg-column">
|
||||
<div class="p-12 py-xl-10 px-xl-20">
|
||||
<a class="d-block" href="{% url 'dashboard' %}">
|
||||
<img src="https://ik.imagekit.io/litepaych/assets/new/img/logo_litepay_2020_white_small.png" class="h-10" alt="...">
|
||||
</a>
|
||||
<div class="mt-16">
|
||||
<h1 class="ls-tight font-bolder display-6 text-white mb-5">
|
||||
Accept crypto currencies
|
||||
<span class="d-xxl-block"> easy!</span>
|
||||
</h1>
|
||||
<p class="text-white text-opacity-80 pe-xl-24">
|
||||
Login or register to start :-)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-auto ps-16 ps-xl-20">
|
||||
<img class="img-fluid rounded-top-start-4" alt="..." src="https://ik.imagekit.io/litepaych/assets/new/img/hero_8.png " />
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-12 col-lg-7 offset-lg-5 min-h-screen overflow-y-auto d-flex flex-column justify-content-center position-relative bg-surface-primary rounded-top-start-lg-4 border-start-lg shadow-soft-5">
|
||||
<div class="w-md-1/2 w-xxl-2/5 mx-auto px-10 px-md-0 py-10">
|
||||
<div class="mb-10">
|
||||
<a class="d-inline-block d-lg-none mb-10" href="">
|
||||
<img src="https://ik.imagekit.io/litepaych/assets/new/img/logo_litepay_2020_blue.png" class="h-10" alt="...">
|
||||
</a>
|
||||
<h1 class="ls-tight font-bolder h3">
|
||||
Sign in to your account
|
||||
</h1>
|
||||
<div class="mt-3 text-sm text-muted">
|
||||
<span>Don't have an account?</span>
|
||||
<a href="{% url 'register' %}" class="font-semibold">Sign up</a>.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
<div class="mb-5">
|
||||
<label class="form-label" for="email">Email address</label>
|
||||
<input type="text" class="form-control" name="email" autofocus autocapitalize="none" autocomplete="email" maxlength="254" required id="email">
|
||||
</div>
|
||||
<div class="mb-5">
|
||||
<div class="d-flex justify-content-between gap-2 mb-2 align-items-center">
|
||||
<label class="form-label mb-0" for="id_auth-password">Password</label>
|
||||
<a href="{% url 'password_reset' %}" class="text-sm text-muted text-primary-hover text-underline">Forgot password?</a>
|
||||
</div>
|
||||
<input type="password" class="form-control" type="password" name="password" autocomplete="password" required id="password">
|
||||
</div>
|
||||
<div>
|
||||
<button type="submit" class="btn btn-primary">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<!-- messages -->
|
||||
{% if messages %}
|
||||
<ul class="messages text-center">
|
||||
{% for message in messages %}
|
||||
<p{% if message.tags %} class="{{ message.tags }}" {% endif %}>{{ message }}</p>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,86 +0,0 @@
|
|||
{% load static %}
|
||||
<!doctype html>
|
||||
<html lang="en" data-theme="light">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||
<meta name="color-scheme" content="dark light">
|
||||
<title>{% block title %}{% endblock title %} | Litepay.ch </title>
|
||||
<!-- App favicon -->
|
||||
<link rel="shortcut icon" href="{% static 'images/favicon.ico'%}">
|
||||
{% block css %}
|
||||
<!-- Styles -->
|
||||
<link rel="stylesheet" type="text/css" href="{% static '/css/main.css'%}">
|
||||
<link rel="stylesheet" type="text/css" href="{% static '/css/utility.css'%}">
|
||||
<!-- Bootstrap Icons -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.2/font/bootstrap-icons.css">
|
||||
<!-- Fonts -->
|
||||
<link rel="stylesheet" href="https://api.fontshare.com/v2/css?f=satoshi@900,700,500,300,401,400&display=swap">
|
||||
{% endblock css %}
|
||||
</head>
|
||||
|
||||
|
||||
|
||||
|
||||
<body>
|
||||
<div class="row g-0 justify-content-center gradient-bottom-right start-purple-500 middle-indigo-500 end-pink-500">
|
||||
<div class="col-md-6 col-lg-5 col-xl-5 position-fixed start-0 top-0 h-screen overflow-y-hidden d-none d-lg-flex flex-lg-column">
|
||||
<div class="p-12 py-xl-10 px-xl-20">
|
||||
<a class="d-block" href="{% url 'dashboard' %}">
|
||||
<img src="https://ik.imagekit.io/litepaych/assets/new/img/logo_litepay_2020_white_small.png" class="h-10" alt="...">
|
||||
</a>
|
||||
<div class="mt-16">
|
||||
<h1 class="ls-tight font-bolder display-6 text-white mb-5">
|
||||
Accept crypto currencies
|
||||
<span class="d-xxl-block"> easy!</span>
|
||||
</h1>
|
||||
<p class="text-white text-opacity-80 pe-xl-24">
|
||||
Login or register to start :-)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-auto ps-16 ps-xl-20">
|
||||
<img class="img-fluid rounded-top-start-4" alt="..." src="https://ik.imagekit.io/litepaych/assets/new/img/hero_8.png " />
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-12 col-lg-7 offset-lg-5 min-h-screen overflow-y-auto d-flex flex-column justify-content-center position-relative bg-surface-primary rounded-top-start-lg-4 border-start-lg shadow-soft-5">
|
||||
<div class="w-md-1/2 w-xxl-2/5 mx-auto px-10 px-md-0 py-10">
|
||||
<div class="mb-10">
|
||||
<a class="d-inline-block d-lg-none mb-10" href="">
|
||||
<img src="https://ik.imagekit.io/litepaych/assets/new/img/logo_litepay_2020_blue.png" class="h-10" alt="...">
|
||||
</a>
|
||||
<h1 class="ls-tight font-bolder h3">
|
||||
Reset your password
|
||||
</h1>
|
||||
<div class="mt-3 text-sm text-muted">
|
||||
<span>Don't have an account?</span>
|
||||
<a href="{% url 'register' %}" class="font-semibold">Sign up</a>.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
<div class="mb-5">
|
||||
<label class="form-label" for="email">Email address</label>
|
||||
<input type="text" class="form-control" name="email" autofocus autocapitalize="none" autocomplete="email" maxlength="254" required id="email">
|
||||
</div>
|
||||
<div>
|
||||
<button type="submit" class="btn btn-primary">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<!-- messages -->
|
||||
{% if messages %}
|
||||
<ul class="messages text-center">
|
||||
{% for message in messages %}
|
||||
<p{% if message.tags %} class="{{ message.tags }}" {% endif %}>{{ message }}</p>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,93 +0,0 @@
|
|||
{% load static %}
|
||||
<!doctype html>
|
||||
<html lang="en" data-theme="light">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||
<meta name="color-scheme" content="dark light">
|
||||
<title>{% block title %}{% endblock title %} | Litepay.ch </title>
|
||||
<!-- App favicon -->
|
||||
<link rel="shortcut icon" href="{% static 'images/favicon.ico'%}">
|
||||
{% block css %}
|
||||
<!-- Styles -->
|
||||
<link rel="stylesheet" type="text/css" href="{% static '/css/main.css'%}">
|
||||
<link rel="stylesheet" type="text/css" href="{% static '/css/utility.css'%}">
|
||||
<!-- Bootstrap Icons -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.2/font/bootstrap-icons.css">
|
||||
<!-- Fonts -->
|
||||
<link rel="stylesheet" href="https://api.fontshare.com/v2/css?f=satoshi@900,700,500,300,401,400&display=swap">
|
||||
{% endblock css %}
|
||||
</head>
|
||||
|
||||
|
||||
|
||||
|
||||
<body>
|
||||
<div class="row g-0 justify-content-center gradient-bottom-right start-purple-500 middle-indigo-500 end-pink-500">
|
||||
<div class="col-md-6 col-lg-5 col-xl-5 position-fixed start-0 top-0 h-screen overflow-y-hidden d-none d-lg-flex flex-lg-column">
|
||||
<div class="p-12 py-xl-10 px-xl-20">
|
||||
<a class="d-block" href="{% url 'dashboard' %}">
|
||||
<img src="https://ik.imagekit.io/litepaych/assets/new/img/logo_litepay_2020_white_small.png" class="h-10" alt="...">
|
||||
</a>
|
||||
<div class="mt-16">
|
||||
<h1 class="ls-tight font-bolder display-6 text-white mb-5">
|
||||
Accept crypto currencies
|
||||
<span class="d-xxl-block"> easy!</span>
|
||||
</h1>
|
||||
<p class="text-white text-opacity-80 pe-xl-24">
|
||||
Login or register to start :-)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-auto ps-16 ps-xl-20">
|
||||
<img class="img-fluid rounded-top-start-4" alt="..." src="https://ik.imagekit.io/litepaych/assets/new/img/hero_8.png " />
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-12 col-lg-7 offset-lg-5 min-h-screen overflow-y-auto d-flex flex-column justify-content-center position-relative bg-surface-primary rounded-top-start-lg-4 border-start-lg shadow-soft-5">
|
||||
<div class="w-md-1/2 w-xxl-2/5 mx-auto px-10 px-md-0 py-10">
|
||||
<div class="mb-10">
|
||||
<a class="d-inline-block d-lg-none mb-10" href="">
|
||||
<img src="https://ik.imagekit.io/litepaych/assets/new/img/logo_litepay_2020_blue.png" class="h-10" alt="...">
|
||||
</a>
|
||||
<h1 class="ls-tight font-bolder h3">
|
||||
Input your new password
|
||||
</h1>
|
||||
<div class="mt-3 text-sm text-muted">
|
||||
<span>Don't have an account?</span>
|
||||
<a href="{% url 'register' %}" class="font-semibold">Sign up</a>.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
<div class="mb-5">
|
||||
<label class="form-label" for="id_new_password1">New Password</label>
|
||||
<input type="password" name="new_password1" autocomplete="new-password" class="form-control" required id="id_new_password1" placeholder="Enter password"/>
|
||||
</div>
|
||||
<div class="mb-5">
|
||||
<div class="d-flex justify-content-between gap-2 mb-2 align-items-center">
|
||||
<label class="form-label mb-0" for="id_auth-id_new_password2">New Password Confirmation</label>
|
||||
</div>
|
||||
<input type="password" class="form-control" type="password" name="new_password2" autocomplete="password" required id="new_password2" placeholder="Confirm password">
|
||||
</div>
|
||||
<div>
|
||||
<button type="submit" class="btn btn-primary">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<!-- messages -->
|
||||
<div >
|
||||
{% if messages %}
|
||||
<ul class="messages text-center">
|
||||
{% for message in messages %}
|
||||
<p{% if message.tags %} class="{{ message.tags }}" {% endif %}>{{ message }}</p>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,125 +0,0 @@
|
|||
{% load static %}
|
||||
<!doctype html>
|
||||
<html lang="en" data-theme="light">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||
<meta name="color-scheme" content="dark light">
|
||||
<title>{% block title %} {{title}} {% endblock title %} | Litepay.ch </title>
|
||||
<!-- App favicon -->
|
||||
<link rel="shortcut icon" href="{% static 'images/favicon.ico'%}">
|
||||
{% block css %}
|
||||
<!-- Styles -->
|
||||
<link rel="stylesheet" type="text/css" href="{% static '/css/main.css'%}">
|
||||
<link rel="stylesheet" type="text/css" href="{% static '/css/utility.css'%}">
|
||||
<!-- Bootstrap Icons -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.2/font/bootstrap-icons.css">
|
||||
<!-- Fonts -->
|
||||
<link rel="stylesheet" href="https://api.fontshare.com/v2/css?f=satoshi@900,700,500,300,401,400&display=swap">
|
||||
{% endblock css %}
|
||||
</head>
|
||||
|
||||
|
||||
<body>
|
||||
<div class="row g-0 justify-content-center gradient-bottom-right start-purple-500 middle-indigo-500 end-pink-500">
|
||||
<div class="col-md-6 col-lg-5 col-xl-5 position-fixed start-0 top-0 h-screen overflow-y-hidden d-none d-lg-flex flex-lg-column">
|
||||
<div class="p-12 py-xl-10 px-xl-20">
|
||||
<a class="d-block" href="{% url 'dashboard' %}">
|
||||
<img src="https://ik.imagekit.io/litepaych/assets/new/img/logo_litepay_2020_white_small.png" class="h-10" alt="...">
|
||||
</a>
|
||||
<div class="mt-16">
|
||||
<h1 class="ls-tight font-bolder display-6 text-white mb-5">
|
||||
Accept crypto currencies
|
||||
<span class="d-xxl-block"> easy!</span>
|
||||
</h1>
|
||||
<p class="text-white text-opacity-80 pe-xl-24">
|
||||
Login or register to start :-)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-auto ps-16 ps-xl-20">
|
||||
<img class="img-fluid rounded-top-start-4" alt="..." src="https://ik.imagekit.io/litepaych/assets/new/img/hero_8.png" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-12 col-lg-7 offset-lg-5 min-h-screen overflow-y-auto d-flex flex-column justify-content-center position-relative bg-surface-primary rounded-top-start-lg-4 border-start-lg shadow-soft-5">
|
||||
<div class="w-md-1/2 w-xxl-2/5 mx-auto px-10 px-md-0 py-10">
|
||||
<div class="mb-10">
|
||||
<a class="d-inline-block d-lg-none mb-10" href="/pages/dashboard.html">
|
||||
<img src="https://ik.imagekit.io/litepaych/assets/new/img/logo_litepay_2020_blue.png" class="h-10" alt="...">
|
||||
</a>
|
||||
<h1 class="ls-tight font-bolder h3">
|
||||
Get started. It's free
|
||||
</h1>
|
||||
<div class="mt-3 text-sm text-muted">
|
||||
<span>Already have an account?</span>
|
||||
<a href="{% url 'login' %}" class="font-semibold">Sign in</a> to your account.
|
||||
</div>
|
||||
</div>
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
<div class="row g-5">
|
||||
<div class="col-sm-6">
|
||||
<label class="form-label">First name</label>
|
||||
<input type="text" class="form-control" name="first_name"/>
|
||||
{% if form.first_name.errors %}
|
||||
{% for error in form.first_name.errors %}
|
||||
<small class="text-danger">{{ error|escape }}</small>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<label class="form-label">Last name</label>
|
||||
<input type="text" class="form-control" name="last_name"/>
|
||||
{% if form.last_name.errors %}
|
||||
{% for error in form.last_name.errors %}
|
||||
<small class="text-danger">{{ error|escape }}</small>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<label class="form-label" for="email">Email address</label>
|
||||
<input type="email" class="form-control" name="email" autofocus autocapitalize="none" autocomplete="email" maxlength="254" required id="email" />
|
||||
{% if form.email.errors %}
|
||||
{% for error in form.email.errors %}
|
||||
<small class="text-danger">{{ error|escape }}</small>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<label class="form-label">Password</label>
|
||||
<input type="password" class="form-control" type="password" name="password" required id="password"/>
|
||||
{% if form.password.error %}
|
||||
{% for error in form.password.errors %}
|
||||
<small class="text-danger">{{ error|escape }}</small>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12">
|
||||
<label class="form-label">Password Again</label>
|
||||
<input type="password" type="password_again" class="form-control" name="password_again" required id="password_again" />
|
||||
</div>
|
||||
<div class="col-sm-12 text-center">
|
||||
<button type="submit" class="btn btn-primary">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% for error in form.non_field_errors %}
|
||||
<small class="text-danger text-center">{{ error|escape }}</small>
|
||||
{% endfor %}
|
||||
|
||||
<!-- messages -->
|
||||
{% if messages %}
|
||||
<ul class="messages text-center">
|
||||
{% for message in messages %}
|
||||
<p{% if message.tags %} class="{{ message.tags }}" {% endif %}>{{ message }}</p>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,156 +0,0 @@
|
|||
{% extends "partials/base.html" %}
|
||||
{% load static %}
|
||||
{% block title %}Vendor Edit Page{% endblock title %}
|
||||
{% block content %}
|
||||
|
||||
|
||||
<!-- ============================================================== -->
|
||||
<!-- Start right Content here -->
|
||||
<!-- ============================================================== -->
|
||||
<!-- Main content -->
|
||||
|
||||
|
||||
<div class="flex-fill overflow-y-lg-auto scrollbar bg-surface-primary rounded-top-4 rounded-top-start-lg-4 rounded-top-end-lg-0 border-top border-lg shadow">
|
||||
<main class="container-fluid px-3 py-5 p-lg-6 p-xxl-10">
|
||||
<header class="border-bottom mb-10">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-sm-6 col-12">
|
||||
<h1 class="h2 ls-tight">
|
||||
{% block vendor_title %} {{vendor_title}} {% endblock vendor_title %}
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="nav nav-tabs overflow-x border-0 mt-4">
|
||||
<li class="nav-item">
|
||||
<a href="{% url 'edit-vendor' vendors.vendorUUID %}" class="nav-link">Options</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="{% url 'add-address' vendors.vendorUUID %}" class="nav-link">Addresses</a>
|
||||
<li class="nav-item">
|
||||
<a href="/pages/account-billing.html" class="nav-link">Delete</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</header>
|
||||
|
||||
|
||||
<form method="POST" action="">
|
||||
{% csrf_token %}
|
||||
|
||||
{{ form.non_field_errors }}
|
||||
<div class="form-group row">
|
||||
<div class="col-md-2">
|
||||
<label for="coin" class="form-label"> Coins <span><i class="bi bi-patch-question-fill text-danger" title="Choose what coin to accept!"></i></span></label>
|
||||
</div>
|
||||
<div class="col-md-8 col-xl-2">
|
||||
<select id="coin" name="coin" class="form-select" aria-describedby="select coin">
|
||||
{% for coin in coins %}
|
||||
<option value="{{coin.coinSymbol}}"> {{ coin.coinName }} ({{ coin.coinSymbol }}) </option>
|
||||
{% endfor %}
|
||||
|
||||
</select>
|
||||
{% if form.coin.errors %}
|
||||
{% for error in form.coin.errors %}
|
||||
<span id="coinHelpBlock" class="text-danger">{{ error|escape }}</span>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<p class="my-6" />
|
||||
<div class="row align-items-center">
|
||||
<div class="col-md-2">
|
||||
<label for="address" class="form-label"> Address <span><i class="bi bi-patch-question-fill text-danger" title="Where the funds are sent to"></i></span></label>
|
||||
</div>
|
||||
<div class="col-md-8 col-xl-5">
|
||||
<div class="">
|
||||
<div class="input-group position-relative">
|
||||
|
||||
<input id="address" name="address" type="text" class="form-control" placeholder="Address" aria-label="address">
|
||||
</div>
|
||||
{% if form.address.errors %}
|
||||
{% for error in form.address.errors %}
|
||||
<p >{{ error|escape }}</p>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="my-6" />
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="offset-4 col-8">
|
||||
<input name="submit" type="submit" class="btn btn-primary" value="Submit" />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- table for addresses -->
|
||||
<p class="my-10"></p>
|
||||
<div class="col-sm-6 col-12">
|
||||
<h1 class="h2 ls-tight">
|
||||
Addresses
|
||||
</h1>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-nowrap">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th scope="col">Coin</th>
|
||||
<th scope="col">Address</th>
|
||||
<th scope="col">Added</th>
|
||||
<th scope="col">Active</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{% for address in addresses %}
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
<img class="w-5 flex-none"src="{% static '/img/crypto/color/'|add:address.coin|add:'.svg' %}" alt="{{address.coin}}" >
|
||||
</td>
|
||||
<td>
|
||||
{{address.address}}
|
||||
</td>
|
||||
<td>
|
||||
{{address.addrAddDate|timesince}} ago
|
||||
</td>
|
||||
<td>
|
||||
{% if address.addrIsActive == False %}
|
||||
<span class="badge badge-lg badge-dot">
|
||||
<i class="bg-warning"></i> Inactive
|
||||
</span>
|
||||
{% else %}
|
||||
<span class="badge badge-lg badge-dot">
|
||||
<i class="bg-success"></i> Active
|
||||
</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Dashboard -->
|
||||
<!-- End Page-content -->
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- end main content-->
|
||||
{% endblock content %}
|
|
@ -1,175 +0,0 @@
|
|||
{% extends "partials/base.html" %}
|
||||
{% load static %}
|
||||
{% block title %}Vendor Edit Page{% endblock title %}
|
||||
{% block content %}
|
||||
|
||||
|
||||
<!-- ============================================================== -->
|
||||
<!-- Start right Content here -->
|
||||
<!-- ============================================================== -->
|
||||
<!-- Main content -->
|
||||
|
||||
|
||||
<div class="flex-fill overflow-y-lg-auto scrollbar bg-surface-primary rounded-top-4 rounded-top-start-lg-4 rounded-top-end-lg-0 border-top border-lg shadow">
|
||||
<main class="container-fluid px-3 py-5 p-lg-6 p-xxl-10">
|
||||
<header class="border-bottom mb-10">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-sm-6 col-12">
|
||||
<h1 class="h2 ls-tight">
|
||||
{% block vendor_title %} {{vendor_title}} {% endblock vendor_title %}
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="nav nav-tabs overflow-x border-0 mt-4">
|
||||
<li class="nav-item">
|
||||
<a href="#" class="nav-link">Options</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="#" class="nav-link">Addresses</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="#" class="nav-link">Delete</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</header>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<form method="POST" action="">
|
||||
{% csrf_token %}
|
||||
|
||||
{{ form.non_field_errors }}
|
||||
<div class="row align-items-center">
|
||||
<div class="col-md-2">
|
||||
{{ form.vendorWebName.errors }}
|
||||
<label for="{{ form.vendorWebName.id_for_label}}" class="form-label">Website Name <span><i class="bi bi-patch-question-fill text-danger" title="Shown on invoice page"></i></span></label>
|
||||
</div>
|
||||
<div class="col-md-8 col-xl-5">
|
||||
<div class="">
|
||||
<div class="input-group position-relative">
|
||||
<span class="input-group-text"><i class="bi bi-three-dots"></i></span>
|
||||
<input id="vendorWebName" name="vendorWebName" type="text" class="form-control" placeholder="Website Name" aria-label="vendorWebName">
|
||||
</div>
|
||||
{{ form.vendorWebName }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="my-6" />
|
||||
<div class="row align-items-center">
|
||||
<div class="col-md-2">
|
||||
{{ form.vendorWebAddr.errors }}
|
||||
<label for="{{ form.vendorWebAddr.id_for_label}}" class="form-label">Website URL <span><i class="bi bi-patch-question-fill text-danger" title="Shown on invoice page"></i></span></label>
|
||||
</div>
|
||||
<div class="col-md-8 col-xl-5">
|
||||
<div class="">
|
||||
<div class="input-group position-relative">
|
||||
<span class="input-group-text"><i class="bi bi-window"></i></span>
|
||||
<input id="vendorWebAddr" name="vendorWebAddr" type="text" class="form-control" placeholder="Website URL" aria-label="vendorWebAddr">
|
||||
</div>
|
||||
{{ form.vendorWebAddr }}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="my-6" />
|
||||
<div class="row align-items-center">
|
||||
<div class="col-md-2">
|
||||
<label for="vendorNetworkFee" class="form-label">Network Fee % <span><i class="bi bi-patch-question-fill text-danger" title="Max percentage "></i></span> </label>
|
||||
</div>
|
||||
<div class="col-md-8 col-xl-2">
|
||||
<select id="vendorNetworkFee" name="vendorNetworkFee" class="form-select" aria-describedby="vendorNetworkFeeHelpBlock">
|
||||
<option value="0" selected="selected">0%</option>
|
||||
<option value="5">5%</option>
|
||||
<option value="10">10%</option>
|
||||
</select>
|
||||
{% if form.vendorNetworkFee.errors %}
|
||||
{% for error in form.vendorNetworkFee.errors %}
|
||||
<span id="vendorNetworkFeeHelpBlock" class="text-danger">{{ error|escape }}</span>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<p class="my-6" />
|
||||
<div class="row align-items-center">
|
||||
<div class="col-md-2">
|
||||
<label for="vendorPaidNotification" class="form-label">Notifications <span><i class="bi bi-patch-question-fill text-danger" title="Get notified by email for each payment received?"></i></span></label>
|
||||
</div>
|
||||
<div class="col-md-8 col-xl-2">
|
||||
<select id="vendorPaidNotification" name="vendorPaidNotification" class="form-select" aria-describedby="vendorPaidNotificationHelpBlock">
|
||||
<option value="true" selected="selected">Yes</option>
|
||||
<option value="false">No</option>
|
||||
</select>
|
||||
</div>
|
||||
{% if form.vendorPaidNotification.errors %}
|
||||
{% for error in form.vendorPaidNotification.errors %}
|
||||
<span id="vendorPaidNotificationHelpBlock" class="text-danger">{{ error|escape }}</span>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<p class="my-6" />
|
||||
<div class="row align-items-center">
|
||||
<div class="col-md-2">
|
||||
<label for="vendorCoverAmount" class="form-label">Cover Amount <span><i class="bi bi-patch-question-fill text-danger" title="Amount covered by you in case the buyer sends less than required"></i></span> </label>
|
||||
</div>
|
||||
<div class="col-md-8 col-xl-2">
|
||||
<select id="vendorCoverAmount" name="vendorCoverAmount" class="form-select" aria-describedby="vendorCoverAmountHelpBlock">
|
||||
<option value="0" >0%</option>
|
||||
<option value="1" selected="selected">1%</option>
|
||||
<option value="2">2%</option>
|
||||
<option value="3">3%</option>
|
||||
<option value="4">4%</option>
|
||||
<option value="5">5%</option>
|
||||
<option value="6">6%</option>
|
||||
<option value="7">7%</option>
|
||||
<option value="8">8%</option>
|
||||
<option value="9">9%</option>
|
||||
<option value="10">10%</option>
|
||||
</select>
|
||||
{% if form.vendorCoverAmount.errors %}
|
||||
{% for error in form.vendorCoverAmount.errors %}
|
||||
<span id="vendorCoverAmountHelpBlock" class="text-danger">{{ error|escape }}</span>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<p class="my-6" />
|
||||
<div class="form-group row">
|
||||
<div class="col-md-2">
|
||||
<label for="vendorPayWindow" class="form-label">Payment <span><i class="bi bi-patch-question-fill text-danger" title="When should we send you your payments?"></i></span></label>
|
||||
</div>
|
||||
<div class="col-md-8 col-xl-2">
|
||||
<select id="vendorPayWindow" name="vendorPayWindow" class="form-select" aria-describedby="vendorPayWindowHelpBlock">
|
||||
<option value="true" >Hourly</option>
|
||||
<option value="false" selected="selected">Daily</option>
|
||||
</select>
|
||||
{% if form.vendorPayWindow.errors %}
|
||||
{% for error in form.vendorPayWindow.errors %}
|
||||
<span id="vendorPayWindowHelpBlock" class="text-danger">{{ error|escape }}</span>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<hr class="my-6" />
|
||||
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="offset-4 col-8">
|
||||
<input name="submit" type="submit" class="btn btn-primary" value="Submit" />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Dashboard -->
|
||||
<!-- End Page-content -->
|
||||
<!-- end main content-->
|
||||
{% endblock content %}
|
|
@ -1,51 +0,0 @@
|
|||
{% extends "partials/base.html" %}
|
||||
{% load static %}
|
||||
{% block title %}Vendor Edit Page{% endblock title %}
|
||||
{% block content %}
|
||||
|
||||
|
||||
<!-- ============================================================== -->
|
||||
<!-- Start right Content here -->
|
||||
<!-- ============================================================== -->
|
||||
<!-- Main content -->
|
||||
|
||||
|
||||
<div class="flex-fill overflow-y-lg-auto scrollbar bg-surface-primary rounded-top-4 rounded-top-start-lg-4 rounded-top-end-lg-0 border-top border-lg shadow">
|
||||
<main class="container-fluid px-3 py-5 p-lg-6 p-xxl-10">
|
||||
<header class="mb-10">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-sm-6 col-12">
|
||||
<h1 class="h2 ls-tight">
|
||||
{% block vendor_title %} {{vendor_title}} {% endblock vendor_title %}
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
<p class="my-6"></p>
|
||||
</header>
|
||||
<div class="position-relative p-5 text-center text-muted bg-body border border-dashed rounded-5">
|
||||
<svg class="bi mt-5 mb-3" width="48" height="48"><use xlink:href="#check2-circle"></use></svg>
|
||||
<h1 class="text-body-emphasis">Your vendor has been created!</h1>
|
||||
<p class="col-lg-6 mx-auto mb-4 "> Please save the SecretKey as you won't be able to see it again! </p>
|
||||
|
||||
<p class="col-lg-6 mx-auto "> VendorID: <strong> {{vendor.vendor}} </strong></p>
|
||||
<p class="col-lg-6 mx-auto mb-4 "> SecretKey: <strong> {{secret}} </strong></p>
|
||||
|
||||
<p class="col-lg-12 mx-auto mb-8 "> Whats next? Go to Addresses tab and input your crypto addresses. </p>
|
||||
<a class="btn btn-primary rounded-pill" href="{% url 'edit-vendor' vendor.vendorUUID %}"> Lets go! </a>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Dashboard -->
|
||||
<!-- End Page-content -->
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- end main content-->
|
||||
{% endblock content %}
|
|
@ -1,10 +0,0 @@
|
|||
{% autoescape off %}
|
||||
Hi {{ user.username }},
|
||||
|
||||
Welcome to Litepay.ch
|
||||
|
||||
Please click on the link below to confirm your registration:
|
||||
|
||||
http://{{ domain }}{% url 'activate' uidb64=uid token=token %}
|
||||
|
||||
{% endautoescape %}
|
|
@ -1,16 +0,0 @@
|
|||
{% autoescape off %}
|
||||
|
||||
Hello {{ user }},
|
||||
|
||||
To initiate the password reset process for your {{ user.email }} on Litepay.ch,
|
||||
please click the link below:
|
||||
|
||||
{{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}
|
||||
|
||||
If clicking the link above doesn't work, please copy and paste the URL in a new browser
|
||||
window instead.
|
||||
|
||||
Sincerely,
|
||||
The Litepay.ch team
|
||||
|
||||
{% endautoescape %}
|
0
base/templates/base/lp_vendor.html → base/templates/base/vendor.html
Executable file → Normal file
0
base/templates/base/lp_vendorEdit.html → base/templates/base/vendorEdit.html
Executable file → Normal file
|
@ -1,11 +0,0 @@
|
|||
from django.contrib.auth.tokens import PasswordResetTokenGenerator
|
||||
import six
|
||||
|
||||
class AccountActivationTokenGenerator(PasswordResetTokenGenerator):
|
||||
def _make_hash_value(self, user, timestamp):
|
||||
return (
|
||||
six.text_type(user.pk) + six.text_type(timestamp) + six.text_type(user.is_active)
|
||||
)
|
||||
|
||||
account_activation_token = AccountActivationTokenGenerator()
|
||||
|
|
@ -1,26 +1,18 @@
|
|||
from . import views
|
||||
from django.urls import path, include
|
||||
from django.contrib.auth import views as auth_views
|
||||
from django.urls import path
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path('login/', views.LoginPage, name="login"),
|
||||
path('logout/', views.LogoutPage, name="logout"),
|
||||
|
||||
|
||||
path('account/login/', views.LoginPage, name="login"),
|
||||
path('account/logout/', views.LogoutPage, name="logout"),
|
||||
path('account/register/', views.RegiserUser, name="register"),
|
||||
path('account/activate/<uidb64>/<token>', views.activate, name='activate'),
|
||||
path('account/password_reset', views.password_reset_request, name="password_reset"),
|
||||
path('account/reset/<uidb64>/<token>/', views.passwordResetConfirm, name='password_reset_confirm'),
|
||||
|
||||
path('', views.index, name="dashboard"),
|
||||
path('vendor/', views.VendorPage, name="vendor"),
|
||||
path('vendor/edit/<str:vdr>/', views.VendorEditPage, name="edit-vendor"),
|
||||
path('vendor/create', views.VendorCreatePage, name="create-vendor"),
|
||||
path('vendor/address/<str:vdr>/', views.VendorAddrPage, name="add-address"),
|
||||
path('p/', views.MerchInvoice, name="invoice-create"),
|
||||
|
||||
|
||||
path('ipage/<str:inv>/', views.InvoicePage, name="ipage"),
|
||||
path('api', views.ApiInvoice, name='api-invoice-create')
|
||||
#path('vendor-success', views.VendorSuccess, name="vendor-success")
|
||||
]
|
|
@ -2,100 +2,23 @@ from django.shortcuts import render, redirect
|
|||
from django.contrib import messages
|
||||
from django.contrib.auth import authenticate, login, logout
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.db.models import Q
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from django.http import HttpResponse, JsonResponse
|
||||
|
||||
#reg
|
||||
from django.template.loader import render_to_string
|
||||
from django.contrib.sites.shortcuts import get_current_site
|
||||
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
|
||||
from django.utils.encoding import force_bytes, force_str
|
||||
from django.core.mail import EmailMessage
|
||||
|
||||
|
||||
#from django_otp.decorators import otp_required
|
||||
#from django.contrib.auth.views import PasswordResetView
|
||||
#from django.contrib.messages.views import SuccessMessageMixin
|
||||
#from django.core.exceptions import ValidationError
|
||||
#from django.urls import reverse_lazy
|
||||
#from django.contrib.auth.models import BaseUserManager
|
||||
|
||||
# custom
|
||||
from .tokens import account_activation_token
|
||||
from django_otp.decorators import otp_required
|
||||
#
|
||||
from users.models import User
|
||||
from .models import VendorsData, CryptoCoins, VendorsAddresses, InvoiceCreation
|
||||
from .forms import VendorEditForm, VendorAddrAddForm, UserRegistrationForm, PasswordResetForm, SetPasswordForm, InvoiceCreationForm, ApiPaymentCreationForm
|
||||
from .functions import vendor_generator, checksumCheck, UrlValidator, RPCHost, RPCXMR
|
||||
from .rpcs import rpcs, API_FEE
|
||||
import uuid, hashlib, requests
|
||||
|
||||
from .models import VendorsData, CryptoCoins, VendorsAddresses
|
||||
from .forms import VendorEditForm, VendorAddrAddForm
|
||||
from .functions import vendor_generator, checksumCheck
|
||||
import uuid, hashlib
|
||||
|
||||
# Create your views here.
|
||||
def activateEmail(request, user, to_email):
|
||||
mail_subject = 'Activate your user account.'
|
||||
message = render_to_string('base/template_activate_account.html', {
|
||||
'user': user.username,
|
||||
'domain': get_current_site(request).domain,
|
||||
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
|
||||
'token': account_activation_token.make_token(user),
|
||||
'protocol': 'https' if request.is_secure() else 'http'
|
||||
})
|
||||
email = EmailMessage(mail_subject, message, to=[to_email])
|
||||
if email.send():
|
||||
messages.success(request, f'Congrats, please check your email and activate your account by \
|
||||
clicking on the activation link. Rememeber to check all folders')
|
||||
else:
|
||||
messages.error(request, f' Unable to send the activation email, please check and retry.')
|
||||
|
||||
|
||||
def activate(request, uidb64, token):
|
||||
try:
|
||||
uid = force_str(urlsafe_base64_decode(uidb64))
|
||||
user = User.objects.get(pk=uid)
|
||||
except(TypeError, ValueError, OverflowError, User.DoesNotExist):
|
||||
user = None
|
||||
|
||||
if user is not None and account_activation_token.check_token(user, token):
|
||||
user.is_active = True
|
||||
user.save()
|
||||
messages.success(request, 'Thank you for your email confirmation. Now you can login your account.')
|
||||
else:
|
||||
messages.error(request, 'Activation link is invalid!')
|
||||
return redirect('login')
|
||||
|
||||
|
||||
@login_required(login_url='login')
|
||||
#@otp_required()
|
||||
def index(request):
|
||||
context = {}
|
||||
return render(request, 'base/lp_dashboard.html', context)
|
||||
|
||||
|
||||
def RegiserUser(request):
|
||||
title = "Register your account"
|
||||
if request.method == "POST":
|
||||
if request.POST.get('password') != request.POST.get('password_again'):
|
||||
messages.error(request, 'Password does not match')
|
||||
return redirect('register')
|
||||
form = UserRegistrationForm(request.POST)
|
||||
if form.is_valid():
|
||||
user = form.save(commit=False)
|
||||
user.email = form.cleaned_data['email'].lower()
|
||||
user.set_password(form.cleaned_data['password'])
|
||||
user.last_name = form.cleaned_data['last_name']
|
||||
user.first_name = form.cleaned_data['first_name']
|
||||
user.uuid = uuid.uuid4()
|
||||
user.is_active = False
|
||||
user.save()
|
||||
activateEmail(request, user, form.cleaned_data.get('email'))
|
||||
return redirect('login')
|
||||
else:
|
||||
form = UserRegistrationForm()
|
||||
|
||||
context = {"form": form, 'title': title}
|
||||
return render(request, 'base/lp_register.html', context)
|
||||
|
||||
return render(request, 'base/dashboard.html', context)
|
||||
|
||||
def LoginPage(request):
|
||||
if request.method == 'POST':
|
||||
|
@ -106,7 +29,7 @@ def LoginPage(request):
|
|||
try:
|
||||
user = User.objects.get(email=email)
|
||||
except:
|
||||
error = messages.error(request, 'Wrong password or account is inactive')
|
||||
error = messages.error(request, 'Email not registered')
|
||||
|
||||
if user is not None and error is None:
|
||||
user = authenticate(request, email=email, password=password)
|
||||
|
@ -114,87 +37,21 @@ def LoginPage(request):
|
|||
login(request, user)
|
||||
return redirect('dashboard')
|
||||
else:
|
||||
messages.error(request, 'Wrong password or account is inactive')
|
||||
messages.error(request, 'Wrong password')
|
||||
|
||||
context = {'title': 'Sign In'}
|
||||
return render(request, 'base/lp_login.html', context)
|
||||
|
||||
context = {}
|
||||
return render(request, 'base/loogin2.html', context)
|
||||
|
||||
def LogoutPage(request):
|
||||
logout(request)
|
||||
return redirect('login')
|
||||
|
||||
def password_reset_request(request):
|
||||
title = "Password reset"
|
||||
if request.method == 'POST':
|
||||
form = PasswordResetForm(request.POST)
|
||||
user = None
|
||||
if form.is_valid():
|
||||
email = form.cleaned_data['email'].lower()
|
||||
try:
|
||||
user = User.objects.get(email=email)
|
||||
except:
|
||||
messages.success(request, 'If the email is registered with us, you will receive an email with instructions for resetting your password.')
|
||||
if user:
|
||||
subject = "Password reset requested on Litepay.ch"
|
||||
message = render_to_string("base/template_password_reset_email.html", {
|
||||
'user': user,
|
||||
'domain': get_current_site(request).domain,
|
||||
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
|
||||
'token': account_activation_token.make_token(user),
|
||||
"protocol": 'https' if request.is_secure() else 'http'
|
||||
})
|
||||
email = EmailMessage(subject, message, to=[user.email])
|
||||
if email.send():
|
||||
messages.success(request,
|
||||
"""
|
||||
If the email is registered with us, you will receive an email with instructions for resetting your password.
|
||||
"""
|
||||
)
|
||||
else:
|
||||
messages.error(request, "Problem sending reset password email, please try again")
|
||||
return redirect('login')
|
||||
else:
|
||||
form = PasswordResetForm()
|
||||
|
||||
context = {"form": form, 'title': title}
|
||||
return render(request, "base/lp_pswd_reset.html", context)
|
||||
|
||||
def passwordResetConfirm(request, uidb64, token):
|
||||
title = "Password reset"
|
||||
try:
|
||||
uid = force_str(urlsafe_base64_decode(uidb64))
|
||||
user = User.objects.get(pk=uid)
|
||||
except(TypeError, ValueError, OverflowError, User.DoesNotExist):
|
||||
user = None
|
||||
|
||||
if user is not None and account_activation_token.check_token(user, token):
|
||||
if request.method == 'POST':
|
||||
form = SetPasswordForm(user, request.POST)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
messages.success(request, "Your password has been set. You may go ahead and log in.")
|
||||
return redirect('login')
|
||||
else:
|
||||
for error in list(form.errors.values()):
|
||||
messages.error(request, error)
|
||||
context = {}
|
||||
return render(request, 'base/lp_pswd_reset_confirm.html', context)
|
||||
else:
|
||||
messages.error(request, "Link is expired")
|
||||
return redirect("dashboard")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#### VENDOR VIEWS ####
|
||||
|
||||
@login_required(login_url='login')
|
||||
def VendorPage(request):
|
||||
vendors = VendorsData.objects.filter(Q(vendorid_id=request.user.id) & Q(vendorDeleted=False))
|
||||
context = {'vendors': vendors}
|
||||
return render(request, 'base/lp_vendor.html', context)
|
||||
return render(request, 'base/vendor.html', context)
|
||||
|
||||
@login_required(login_url='login')
|
||||
#@otp_required(login_url='two_factor:login')
|
||||
|
@ -217,7 +74,7 @@ def VendorEditPage(request, vdr ):
|
|||
except Exception as e:
|
||||
messages.error(request, "Something wrong happened, try again.")
|
||||
context = {'vendors': vendors, 'form': form, 'vendor_title': vendor_title}
|
||||
return render(request, 'base/lp_vendorEdit.html', context)
|
||||
return render(request, 'base/vendorEdit.html', context)
|
||||
except Exception as e:
|
||||
messages.error(request, e)
|
||||
return redirect('vendor')
|
||||
|
@ -260,14 +117,14 @@ def VendorCreatePage(request):
|
|||
new_vendor.save()
|
||||
vendor_title = "Congrats!"
|
||||
context = {'vendor_title': vendor_title, "vendor": new_vendor, 'secret': secretKey}
|
||||
return render(request, 'base/lp_vendorSuccess.html', context)
|
||||
return render(request, 'base/vendorSuccess.html', context)
|
||||
except Exception:
|
||||
messages.error(request, "Unable to create vendor") #
|
||||
else:
|
||||
messages.error(request, "The information submited is incomplete") #
|
||||
except Exception as e:
|
||||
messages.error(request, "Something wrong happened, try again.")
|
||||
return render(request, 'base/lp_vendorCreate.html', context)
|
||||
return render(request, 'base/vendorCreate.html', context)
|
||||
|
||||
@login_required(login_url='login')
|
||||
def VendorAddrPage(request,vdr):
|
||||
|
@ -285,22 +142,14 @@ def VendorAddrPage(request,vdr):
|
|||
if request.POST.get('submit') == 'Submit':
|
||||
try:
|
||||
if checksumCheck(request.POST.get('coin').lower(), request.POST.get('address')) == False:
|
||||
messages.error(request, "Invalid address, please try again")
|
||||
messages.error(request, "Invalid address")
|
||||
context = {'vendor_title': vendor_title, 'coins': coins, 'vendors': vendors, "addresses": addresses}
|
||||
return render(request, 'base/lp_vendorAddr.html', context)
|
||||
return render(request, 'base/vendorAddr.html', context)
|
||||
except:
|
||||
# stop here, return nothing, notify us.
|
||||
return redirect('vendorAddr', vdr)
|
||||
|
||||
##check if duplicate
|
||||
try:
|
||||
for obj in VendorsAddresses.objects.filter(Q(coin=request.POST.get('coin')) & Q(addrIsActive=True) & Q(vendorUUID=vdr) & Q(vendorid_id=request.user.id)):
|
||||
if obj.address == request.POST.get('address'):
|
||||
messages.error(request, "Address already exists")
|
||||
context = {'vendor_title': vendor_title, 'coins': coins, 'vendors': vendors, "addresses": addresses}
|
||||
return render(request, 'base/lp_vendorAddr.html', context)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
try:
|
||||
form = VendorAddrAddForm(request.POST)
|
||||
|
@ -319,7 +168,7 @@ def VendorAddrPage(request,vdr):
|
|||
messages.success(request, "Vendor address saved")
|
||||
#add email notification
|
||||
context = {'vendor_title': vendor_title, 'coins': coins, 'vendors': vendors, "addresses": addresses}
|
||||
return render(request, 'base/lp_vendorAddr.html', context)
|
||||
return render(request, 'base/vendorAddr.html', context)
|
||||
except Exception as e:
|
||||
messages.error(request, e) #
|
||||
else:
|
||||
|
@ -328,182 +177,8 @@ def VendorAddrPage(request,vdr):
|
|||
messages.error(request, "Something wrong happened, try again!")
|
||||
|
||||
context = {'vendor_title': vendor_title, 'coins': coins, 'vendors': vendors, "addresses": addresses}
|
||||
return render(request, 'base/lp_vendorAddr.html', context)
|
||||
return render(request, 'base/vendorAddr.html', context)
|
||||
except Exception as e:
|
||||
messages.error(request, "Something wrong happened, try again!")
|
||||
return redirect('vendor')
|
||||
|
||||
@csrf_exempt
|
||||
def MerchInvoice(request):
|
||||
if request.method == 'GET':
|
||||
return HttpResponse(status=403)
|
||||
elif request.method == 'POST':
|
||||
|
||||
required_fields = ['vendor', 'secret', 'callback', 'return', 'invoice']
|
||||
for field in required_fields:
|
||||
if request.POST.get(field) is None or request.POST.get(field).strip() == '':
|
||||
return JsonResponse({'status': 'error', 'message': f'You did not send the {field} field, try again.'}, status=400)
|
||||
|
||||
price = request.POST.get('price')
|
||||
currency = request.POST.get('currency')
|
||||
callbackurl = requests.utils.unquote(request.POST.get('callback'))
|
||||
returnurl = requests.utils.unquote(request.POST.get('return'))
|
||||
email = request.POST.get('email')
|
||||
|
||||
|
||||
if not currency:
|
||||
currency = 'USD'
|
||||
|
||||
if price is None or not price.isdigit() or int(price) <= 0:
|
||||
return JsonResponse({'status': 'error', 'message': 'You did not send a valid price, try again.'}, status=400)
|
||||
|
||||
if UrlValidator.validate(requests.utils.unquote(request.POST.get('callback')))!= True:
|
||||
return JsonResponse({'status': 'error', 'message': 'Invalid callback URL'}, status=400)
|
||||
if UrlValidator.validate(requests.utils.unquote(request.POST.get('return'))) != True:
|
||||
return JsonResponse({'status': 'error', 'message': 'Invalid return URL'}, status=400)
|
||||
|
||||
try:
|
||||
vendor = VendorsData.objects.get(vendor=request.POST.get('vendor'))
|
||||
except:
|
||||
return JsonResponse({'status': 'error', 'message':'Vendor ID unknown'}, status=400)
|
||||
|
||||
if vendor.vendorSecretKey != hashlib.md5(request.POST.get('secret').encode()).hexdigest():
|
||||
return JsonResponse({'status': 'error', 'message': 'Invalid secret key'}, status=400)
|
||||
|
||||
invUUID = uuid.uuid5(uuid.NAMESPACE_URL,request.POST.get('invoice')+request.POST.get('vendor'))
|
||||
|
||||
if InvoiceCreation.objects.filter(Q(invoiceUUID=invUUID)):
|
||||
protocol = 'https' if request.is_secure() else 'http'
|
||||
domain = get_current_site(request).domain + '/v2/i/' + str(invUUID)
|
||||
return JsonResponse({'status': 'success', 'url': protocol +'://'+ domain }, status=200)
|
||||
|
||||
try:
|
||||
form = InvoiceCreationForm()
|
||||
newForm = form.save(commit=False)
|
||||
newForm.invoiceUUID = invUUID
|
||||
newForm.invoiceID = request.POST.get('invoice')
|
||||
newForm.invoiceAmount = request.POST.get('price')
|
||||
newForm.invoiceCoin = currency
|
||||
newForm.invoiceState = 0
|
||||
newForm.invoiceCallbackLink = callbackurl
|
||||
newForm.invoiceReturnLink = returnurl
|
||||
newForm.invoiceBuyerEmail = email
|
||||
newForm.invoiceDeleteLink = None
|
||||
newForm.invoiceDeleted = 0
|
||||
newForm.invoiceVendor_id = vendor.id
|
||||
newForm.invoiceVendorid_id = vendor.vendorid_id
|
||||
try:
|
||||
newForm.save()
|
||||
protocol = 'https' if request.is_secure() else 'http'
|
||||
domain = get_current_site(request).domain + '/v2/i/' + str(invUUID)
|
||||
return JsonResponse({'status': 'success', 'url': protocol +'://'+ domain }, status=200)
|
||||
except Exception as e:
|
||||
return JsonResponse({'status': 'error', 'message': 'Unable to save the invoice, try again'}, status=400)
|
||||
except Exception as e:
|
||||
return JsonResponse({'status': 'error', 'message': 'Unable to create the invoice, try again'}, status=400)
|
||||
else:
|
||||
return HttpResponse(status=403)
|
||||
|
||||
@csrf_exempt
|
||||
def ApiInvoice(request):
|
||||
if request.method == 'GET':
|
||||
required_fields = ['method', 'address']
|
||||
for field in required_fields:
|
||||
if request.GET.get(field) is None or request.GET.get(field).strip() == '':
|
||||
return JsonResponse({'status': 'error', 'message': f'You did not send the {field} field, try again.'}, status=400)
|
||||
|
||||
try:
|
||||
if not CryptoCoins.objects.filter(Q(coinAPI=True) & Q(coinIsActive=True) & Q(coinSymbol = request.GET.get('method').upper())):
|
||||
return JsonResponse({'status': 'error', 'message': 'Invalid method used'}, status=400)
|
||||
except Exception:
|
||||
return JsonResponse({'status': 'error', 'message': 'Something wrong happened, try again!'}, status=400)
|
||||
|
||||
if checksumCheck(request.GET.get('method').lower(), request.GET.get('address')) == False:
|
||||
return JsonResponse({'status': 'error', 'message': 'Invalid destination address'}, status=400)
|
||||
|
||||
if request.GET.get('callback_url'):
|
||||
if UrlValidator.validate(requests.utils.unquote(request.GET.get('callback_url'))) != True:
|
||||
return JsonResponse({'status': 'error', 'message': 'Invalid callback URL'}, status=400)
|
||||
statusFlag = 0
|
||||
callbackurl = requests.utils.unquote(request.GET.get('callback_url'))
|
||||
else:
|
||||
statusFlag = 1
|
||||
callbackurl = None
|
||||
|
||||
## RPC connection to Demons
|
||||
match request.GET.get('method').upper():
|
||||
case 'BTC' | 'LTC' | 'ZEC' | 'BCH' | 'BTCT' | 'DOGE':
|
||||
rpc = RPCHost("http://%s:%s@%s:%s" % (rpcs[request.GET.get('method').upper()]['user'], rpcs[request.GET.get('method').upper()]['pass'], rpcs[request.GET.get('method').upper()]['host'], rpcs[request.GET.get('method').upper()]['port']))
|
||||
case 'XMR':
|
||||
rpc = RPCXMR(rpcs[request.GET.get('method').upper()]['host'], rpcs[request.GET.get('method').upper()]['user'], rpcs[request.GET.get('method').upper()]['pass'])
|
||||
case _:
|
||||
return JsonResponse({'status': 'error', 'message': 'RPC undergoing maintenance'}, status=400)
|
||||
|
||||
try:
|
||||
match request.GET.get('method').upper():
|
||||
case 'XMR':
|
||||
wallet = rpc.call('create_address',{"account_index": 0})
|
||||
wallet = wallet['address']
|
||||
case 'LTC' | 'ZEC' | 'DOGE':
|
||||
#wallet = rpc.call('createwallet','test',False,False,'exdTHnRJ1BxZfBvU',False,False,True)
|
||||
wallet = rpc.call('getnewaddress')
|
||||
case 'BTC' | 'BTCT':
|
||||
#wallet = rpc.call('createwallet','test',False,False,'exdTHnRJ1BxZfBvU',False,True,True,False)
|
||||
wallet = rpc.call('getnewaddress', '', 'p2sh-segwit')
|
||||
case 'BCH':
|
||||
wallet = rpc.call('getnewaddress')
|
||||
wallet = wallet.replace('bitcoincash:', '')
|
||||
case _:
|
||||
## notify admin about the error
|
||||
return JsonResponse({'status': 'error', 'message': 'CryptoCoin unavailable'}, status=400)
|
||||
except Exception as error:
|
||||
## notify admin about the error
|
||||
# Failed to connect for remote procedure call.
|
||||
return JsonResponse({'status': 'error', 'message': 'RPC unavailable'}, status=400)
|
||||
|
||||
|
||||
try:
|
||||
form = ApiPaymentCreationForm()
|
||||
newForm = form.save(commit=False)
|
||||
newForm.userUUID = uuid.uuid5(uuid.NAMESPACE_URL,request.GET.get('address'))
|
||||
newForm.userAddr = request.GET.get('address')
|
||||
newForm.userCoin = request.GET.get('method').upper()
|
||||
newForm.usercallbackUrl = callbackurl
|
||||
newForm.userIP = request.META.get("REMOTE_ADDR")
|
||||
newForm.ourAddr = wallet
|
||||
newForm.userAmount = 0.00000000
|
||||
newForm.statusFlag = statusFlag
|
||||
newForm.paidFlag = 0
|
||||
try:
|
||||
newForm.save()
|
||||
return JsonResponse(
|
||||
{'status': 'success',
|
||||
'callback_url': callbackurl,
|
||||
'address': wallet,
|
||||
'destination': request.GET.get('address'),
|
||||
'fee': API_FEE
|
||||
}, status=200)
|
||||
except Exception as e:
|
||||
return JsonResponse({'status': 'error', 'message': 'Unable to save the invoice, try again'}, status=400)
|
||||
except Exception as e:
|
||||
return JsonResponse({'status': 'error', 'message': 'Unable to create the invoice, try again'}, status=400)
|
||||
|
||||
elif request.method == 'POST':
|
||||
return HttpResponse(status=403)
|
||||
else:
|
||||
return HttpResponse(status=403)
|
||||
|
||||
|
||||
def InvoicePage(request, inv):
|
||||
try:
|
||||
invoice = InvoiceCreation.objects.get(invoiceUUID=inv)
|
||||
vendor = VendorsData.objects.get(Q(id=invoice.invoiceVendor_id))
|
||||
vendorCryptoCoins = VendorsAddresses.objects.filter(Q(addrIsActive=True) & Q(vendor_id=invoice.invoiceVendor_id))
|
||||
|
||||
|
||||
|
||||
context = {'invoice': invoice, 'coins': vendorCryptoCoins, "vendor": vendor}
|
||||
return render(request, 'base/lp_invoice.html', context)
|
||||
except Exception as e:
|
||||
return HttpResponse(e)
|
||||
#return redirect('dashboard')
|
BIN
base/templates/base/._lp_invoice.html → dLitepay/.DS_Store
vendored
Executable file → Normal file
|
@ -191,11 +191,4 @@ SECURE_SSL_REDIRECT = False #to be switched to true when in prod
|
|||
SESSION_COOKIE_AGE = 3600
|
||||
TWO_FACTOR_REMEMBER_COOKIE_AGE = 3600
|
||||
SERVER_EMAIL = 'info@litepay.ch'
|
||||
DEFAULT_FROM_EMAIL = 'info@litepay.ch'
|
||||
|
||||
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
|
||||
EMAIL_HOST = 'smtp.gmail.com'
|
||||
EMAIL_USE_TLS = True
|
||||
EMAIL_PORT = 587
|
||||
EMAIL_HOST_USER = 'x'
|
||||
EMAIL_HOST_PASSWORD = 'x'
|
||||
DEFAULT_FROM_EMAIL = 'info@litepay.ch'
|
|
@ -19,13 +19,12 @@ from django.urls import path, include
|
|||
from two_factor.urls import urlpatterns as tf_urls
|
||||
urlpatterns = [
|
||||
#path('', include(tf_urls)),
|
||||
path('', include('base.urls')),
|
||||
path('admin/', admin.site.urls),
|
||||
path('', include('base.urls'))
|
||||
]
|
||||
|
||||
'''
|
||||
urlpatterns = [
|
||||
|
||||
path('admin/', admin.site.urls),
|
||||
|
||||
]
|
||||
'''
|
|
@ -1,77 +0,0 @@
|
|||
/* Define styles for centering the outer square */
|
||||
body {
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
display: flex;
|
||||
background-color: rgb(247, 247, 247);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 0 0 0 30%;
|
||||
width: 600px; /* Adjust for smaller screens */
|
||||
height: 100vh; /* Ensure full viewport height for vertical centering */
|
||||
margin: 0; /* Remove default margin */
|
||||
}
|
||||
|
||||
/* Style for the outer square */
|
||||
.outer-square {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex: 1 0 21%; /* explanation below */
|
||||
border-radius: 15px; /* Add rounded corners to the outer square */
|
||||
}
|
||||
|
||||
/* Style for the nested square */
|
||||
.inner-square {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
/* background-color: white; Change the background to white */
|
||||
margin: 15px; /* Add margin of 15px to push it away from the outer square's edge */
|
||||
border-radius: 10%; /* Create a circle for the inner square */
|
||||
/* border: 2px solid rgb(247, 247, 247); Add a blue 2px border */
|
||||
position: relative; /* Enable positioning for the content */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 1%;
|
||||
}
|
||||
.image {
|
||||
padding-top: 10%;
|
||||
}
|
||||
|
||||
/* Style for the h1 tag */
|
||||
h1 {
|
||||
text-align: center;
|
||||
padding: auto;
|
||||
}
|
||||
|
||||
.crypto-info h1 {
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
}
|
||||
.crypto-info p {
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
padding: auto;
|
||||
}
|
||||
|
||||
.crypto-info img {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
@media (max-width: 500px) {
|
||||
|
||||
.inner-square {
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.crypto-info h1 {
|
||||
padding-left: 10px;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,282 +0,0 @@
|
|||
/* styles.css */
|
||||
body {
|
||||
margin: auto;
|
||||
padding: 0;
|
||||
background-color: rgb(247, 247, 247);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 100vh;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
width: max-content;
|
||||
}
|
||||
|
||||
.containerCrypto {
|
||||
/* background-color: rgb(254, 254, 254);
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); */
|
||||
border-radius: 20px;
|
||||
padding: 20px 20px;
|
||||
text-align: center;
|
||||
max-width: 80%; /* Adjust the maximum width as desired */
|
||||
width: 500px; /* Set a fixed width as a fallback for smaller screens */
|
||||
margin: 0 auto; /* Center the container horizontally */
|
||||
}
|
||||
.container3 {
|
||||
background-color: rgb(254, 254, 254);
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 20px;
|
||||
padding: 50px;
|
||||
text-align: center;
|
||||
max-width: 80%; /* Adjust the maximum width as desired */
|
||||
width: 500px; /* Set a fixed width as a fallback for smaller screens */
|
||||
margin: 0 auto; /* Center the container horizontally */
|
||||
}
|
||||
.container2 {
|
||||
background-color: rgb(254, 254, 254);
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 15px;
|
||||
padding: 1px 100px;
|
||||
text-align: center;
|
||||
max-width: 80%; /* Adjust the maximum width as desired */
|
||||
width: 500px; /* Set a fixed width as a fallback for smaller screens */
|
||||
margin: 20px auto; /* Center the container horizontally */
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 10px;
|
||||
font-size: 16px;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.textElements {
|
||||
margin: auto;
|
||||
width: max-content;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.textElements img {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.redText {
|
||||
margin-top: -6px;
|
||||
color: red;
|
||||
}
|
||||
|
||||
.selectorContainer {
|
||||
margin: auto;
|
||||
width: max-content;
|
||||
}
|
||||
|
||||
.line {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.cryptos {
|
||||
box-shadow: 1px 3px 8px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 20px;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0 15px;
|
||||
padding: 10px 40px 10px 20px;
|
||||
}
|
||||
|
||||
.crypto img {
|
||||
margin-right: 10px;
|
||||
width: 65px;
|
||||
height: 65px;
|
||||
}
|
||||
|
||||
.line a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.line a h1 {
|
||||
color: #000;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.container {
|
||||
background-color: white;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 10px;
|
||||
padding: 45px 10px;
|
||||
text-align: center;
|
||||
width: 500px; /* Set a fixed width as a fallback for smaller screens */
|
||||
margin: auto; /* Center the container horizontally */
|
||||
}
|
||||
.container2 {
|
||||
background-color: white;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 10px;
|
||||
padding: 15px 10px;
|
||||
text-align: center;
|
||||
width: 500px; /* Set a fixed width as a fallback for smaller screens */
|
||||
margin: 10px auto; /* Center the container horizontally */
|
||||
}
|
||||
|
||||
.line {
|
||||
margin-top: 0px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.crypto {
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 15px 15px;
|
||||
padding: 5px 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
justify-content: space-between;
|
||||
margin-top: 50px;
|
||||
margin-bottom: -35px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.footer p {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.footer2 {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.footer2 p {
|
||||
font-size: 14px;
|
||||
color: rgb(0, 167, 167);
|
||||
}
|
||||
/* Add the following CSS for the new element */
|
||||
.row-container {
|
||||
background-color: white;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 10px;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.row-container img {
|
||||
width: 28%;
|
||||
height: auto;
|
||||
max-width: 100%;
|
||||
margin-right: 20px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.invoice-info {
|
||||
flex: 1;
|
||||
text-align: left; /* Align text to the right */
|
||||
}
|
||||
|
||||
.invoice-info p {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.invoice-info h1 {
|
||||
margin: 10px 0;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
/* ... Previous styles ... */
|
||||
|
||||
.invoice-amount {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.invoice-amount h1 {
|
||||
margin: 0;
|
||||
font-size: 24px;
|
||||
margin-right: 10px; /* Add margin to separate from "To USD" text */
|
||||
}
|
||||
|
||||
.to-usd {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.copy-button {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.copy-button img {
|
||||
border-radius: 0px;
|
||||
box-shadow: 0 0px 0px rgb(255, 255, 255);
|
||||
width: 20px; /* Adjust the width as needed */
|
||||
height: 20px; /* Adjust the height as needed */
|
||||
}
|
||||
|
||||
/* ... Previous styles ... */
|
||||
|
||||
.address-input {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid #ccc;
|
||||
margin-bottom: 10px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.address-input input {
|
||||
flex: 1;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
outline: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.transaction-table {
|
||||
width: 100%;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0;
|
||||
margin-top: 20px;
|
||||
background-color: white;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.transaction-table th,
|
||||
.transaction-table td {
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
border: 1px solid #ddd;
|
||||
font-size: 12px;
|
||||
color: grey;
|
||||
}
|
||||
|
||||
.highlighted-row {
|
||||
background-color: rgba(144, 238, 144, 0.2);
|
||||
border-radius: 10px;
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><path d="M16 32C7.163 32 0 24.837 0 16S7.163 0 16 0s16 7.163 16 16-7.163 16-16 16zm-.065-28C9.342 4.001 4 9.347 4 15.94c.001 6.592 5.347 11.936 11.94 11.935 6.592-.002 11.936-5.347 11.935-11.94A11.937 11.937 0 0015.935 4zm-4.847 5.23a.123.123 0 01.125-.12h4.973a6.98 6.98 0 013.027.628c.18.088.357.186.528.292l-3.237 1.853h-1.689a.123.123 0 00-.12.126v.932l-3.607 2.086V9.23zM9.749 19.708l-2.162-2.184 7.12-4.108v2.662a.123.123 0 00.125.12h1.017l-6.093 3.51h-.007zm10.662-2.03c-1.044.872-2.477 1.308-4.299 1.308h-1.297a.123.123 0 00-.123.123v2.688l-1.81 1.042-1.69.977-.107.06v-4.455l5.603-3.224a2.056 2.056 0 001.297-.513 1.74 1.74 0 00.318-.432l3.578-2.071c.06.328.09.66.089.994.004 1.463-.516 2.63-1.56 3.503zm-1.92-3.019c.024-.153.036-.309.037-.464a2.417 2.417 0 00-.563-1.674A1.823 1.823 0 0017.15 12l4.973-2.871 2.182 2.183-5.814 3.347z"/></svg>
|
Before Width: | Height: | Size: 934 B |
|
@ -1 +0,0 @@
|
|||
<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><path d="M16 32C7.163 32 0 24.837 0 16S7.163 0 16 0s16 7.163 16 16-7.163 16-16 16zm0-4.742c6.218 0 11.258-5.04 11.258-11.258 0-6.218-5.04-11.258-11.258-11.258C9.782 4.742 4.742 9.782 4.742 16c0 6.218 5.04 11.258 11.258 11.258zm0-.662c-5.852 0-10.596-4.744-10.596-10.596S10.148 5.404 16 5.404 26.596 10.148 26.596 16 21.852 26.596 16 26.596zm-1.91-2.464c.248-.102 1.218-.85 2.155-1.655a51.685 51.685 0 003.348-3.113c1.026-1.026 1.407-1.467 1.47-1.695.222-.801-2.205-9.606-2.699-9.795-.301-.116-2.993 2.123-5.377 4.467-1.398 1.374-1.785 1.831-1.815 2.13-.02.231.06.81.209 1.496.593 2.722 1.672 6.483 2.218 7.718.229.524.255.547.49.447z"/></svg>
|
Before Width: | Height: | Size: 725 B |
|
@ -1 +0,0 @@
|
|||
<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><path d="M16 0c8.837 0 16 7.163 16 16s-7.163 16-16 16S0 24.837 0 16 7.163 0 16 0zm-2.158 5.5h-.111c-.7.011-2.772.262-3.596 2.769-.255-.645-.49-1.584-.49-1.584s-.008.006-.02.019l-.055.055c-.29.303-1.301 1.533-.706 3.407a250.273 250.273 0 00-4.09-1.477l-.086-.028a.244.244 0 00-.019-.005c-.127-.019-.163.036-.163.036s-.037.056.072.148c.2.165 4.013 3.02 4.848 3.572-.181.663-.181.976 0 1.29.255.423.273.644.237.957-.037.313-.364 3.02-.436 3.352-.073.331-.835 1.51-.8 1.86.037.35.51 1.841.927 2.007.309.11 1.071.35 1.58.35.181 0 .345-.037.417-.11.309-.277.4-.332.618-.332h.054c.09 0 .2.018.327.018.29 0 .672-.055.944-.313.4-.405 1.09-.958 1.307-1.215.273-.35.418-.83.345-1.308-.054-.442.182-.829.454-1.215.345-.46.98-1.29.98-1.29 1.254.958 2.034 2.413 2.034 4.034 0 2.872-2.469 5.193-5.52 5.193a5.81 5.81 0 01-1.38-.166c1.399.497 2.579.663 3.541.663 2.052 0 3.142-.755 3.142-.755s-.382.497-1 1.068h.02c3.395-.479 5.047-3.315 5.047-3.315s-.127.921-.29 1.547c4.52-3.444 3.758-7.753 3.74-7.9.036.055.49.608.726.902.62-6.467-3.736-9.201-5.035-9.867l-.136-.068a3.867 3.867 0 00-.222-.101s.908.037 1.852.147c-2.124-1.694-4.14-2.191-5.774-2.191-2.251 0-3.776.939-3.867.994l.708-1.141s-.044-.005-.124-.006zm2.248 3.966c3.723.405 6.628 3.61 6.628 7.495a7.549 7.549 0 01-4.23 6.795c1.18-.92 2.087-2.21 2.487-3.665.018-.055.181-.147.29-.22.182-.093.363-.203.4-.35.072-.424.109-.866.109-1.308 0-.166-.164-.331-.327-.497-.091-.11-.236-.24-.236-.332a7.25 7.25 0 00-1.49-3.664c-.362-2.21-1.815-2.891-1.851-2.91l.023.036.049.08c.217.37.808 1.57.255 2.941-.672 1.64-2.397 1.381-2.542 1.4-.146 0-.709.736-1.417 2.099a1.967 1.967 0 00-.908-.055c.327-.921.817-2.228.908-2.339.037-.037.309-.11.49-.166.345-.092.509-.147.563-.22.037-.056.218-.48.4-.921.163 0 .58-.037.617-.056.037-.037.382-.939.382-1.05 0-.091-.709-1.878-.981-2.56a4.31 4.31 0 00.381-.533zm3.686 4.64a6.805 6.805 0 011.271 3.315c.018.148.164.295.309.442.127.11.272.258.272.35 0 .424-.036.847-.109 1.27-.018.056-.181.148-.308.222-.182.092-.345.184-.382.331l-.085.282a6.868 6.868 0 01-2.087 3.09l-.223.18.154-.168c1.582-1.8 2.31-4.635 1.043-6.901.182-.94.2-1.75.145-2.413zM14.783 7.11s.672 1.491-.036 2.578c-.727 1.086-1.435 1.289-1.435 1.289s.999.184 1.925-.497c.381.902.744 1.841.763 1.97l-.347.834-.147.353c-.171.406-.328.772-.36.82-.036.037-.29.11-.472.148-.309.092-.49.147-.563.202-.127.11-.708 1.731-.98 2.523a1.5 1.5 0 00-.89.645c.127-.092.526-.148.817-.184.254-.019 1.035.405 1.235 1.197v.036c.036.295-.055.571-.2.792-.073.092-.381.369-.6.571-.217.203-.453.405-.635.59-.072.073-.218.11-.436.11h-.544c.272-.368 1.071-1.216 1.343-1.4.327-.22.49-.442.29-.828-.199-.387-.725-.295-.725-.295s.308-.129.58-.129c-.344-.092-.78 0-.98.203-.218.202-.181.92-.272 1.38-.091.48-.4.719-.872 1.161-.254.24-.436.313-.58.313a6.189 6.189 0 01-.927-.24c-.181-.239-.454-1.03-.526-1.362.054-.184.272-.571.38-.792.219-.424.346-.663.382-.884.073-.313.309-2.247.4-3.057.236.313.563.829.49 1.16.527-.755.145-1.491-.036-1.786-.164-.295-.382-.884-.2-1.51.181-.626.835-2.357.835-2.357s.218.387.527.313c.308-.074 2.796-3.867 2.796-3.867zm-4.35 11.584s-.595 1.056-.649 1.202c-.054.164.036.455.27.437.235-.018.523-.364.523-.62 0-.327-.288-.29-.288-.29zm2.316.165c.146-.037.49.018.49.276 0 .24-.254.295-.435.46-.127.13-.382.405-.418.442l.001-.001.052-.095c.091-.206.096-.473.105-.617l.006-.06c.018-.13.054-.369.2-.405zm.853-7.464s-1.845 2.937-2.008 2.993c-.163.055-.325-.588-.325-.588-.344 1.34.579 1.524.687 1.102.507-.129 1.375-.68 1.719-1.065.343-.404.162-1.157-.47-1.285.162-.386.397-1.157.397-1.157zm1.02-3.162l-1.198 1.835h.016c.086-.006.482-.063.932-.593.412-.5.25-1.242.25-1.242z"/></svg>
|
Before Width: | Height: | Size: 3.6 KiB |
|
@ -1 +0,0 @@
|
|||
<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><path d="M16 32C7.163 32 0 24.837 0 16S7.163 0 16 0s16 7.163 16 16-7.163 16-16 16zm-.737-7.144v1.463H16V24.13h-1.463v.726h.726zm-7.337-8.03H7.2v3.652h.726v-1.463h.737v-1.463h-.737v-.726zm8.811 4.378v2.189h.726v-2.189h-.726zM16 23.393v.737h.737v-.737H16zm-7.337-.726v2.189h2.2v-2.189h-2.2zM7.2 15.363v.726h.737v-.726H7.2zm4.4-1.463v.737h.737V13.9H11.6zm4.4-.737v1.463h.737v-1.463H16zm-9.537-2.189v2.189h2.2v-2.189h-2.2zm6.6 13.882v1.463h.737v-1.463h-.737zm.737-11.693h-.726v1.463h.726V13.9h.737v-1.463H13.8v.726zm.737-1.452v.726h.726v-.726h-.726zm0 2.189v.726h.726V13.9h-.726zm-3.674 1.463v.726h2.2v-.726h-2.2zm2.937-2.926v-.726h.726v-.737H13.8V9.522h-2.2v.726h1.463v.726h-.737v.726H11.6v.726h-.726v-.715h-.748v-.726h.737v.715h.737v-.726h-.726V9.522H5v5.115h5.874V13.9h.726v-1.463h.737v.726h.737v-.726h.726zM9.4 13.9H5.737v-3.652H9.4V13.9zm.726 0v-1.463h.737V13.9h-.737zm2.937-2.2v-.715h.737v.715h-.737zm5.874 8.041v-.726h-1.474v-1.463h-.726v.726h-.726v-.726h.726v-2.2h-1.463v.737h-.748v1.463H13.8v.726h.737v-.726h.726v2.189H13.8v-.726h-.737v-1.463h-.726v-.726h-1.474V16.1h-.737v-.726H8.663v.726h-.737v.726h.737v.726H9.4v-.726h.737v.726H9.4v.726h.737v.726h.726v-.726h.737v-.726h.726v.726H11.6v.726h-.726v1.463h1.463v.737h-1.474v-.726h-.737v.726H8.663v-.726h-.726v.726H7.2v5.115h5.137V21.93h.726v2.2h1.474v-.726h.737V21.93h-.737v-.726H13.8v.726h-.726v-1.463h2.2v.726h.737v-1.452h1.452v.737h.737v-.737h.737zM11.6 25.582H7.937V21.93H11.6v3.652zm.737-5.841H11.6v-.726h.737v.726zm1.463 2.926h.737v.726H13.8v-.726zm5.137-13.145v1.452h.726V9.522h-.726zm-1.474 0h-.726v2.189H16v.726h.737v.726h.726v1.463h.737v-1.463h.737v1.474h.726V13.9h.737v-1.463h-1.463v-1.463h-1.474V9.522zm6.6 8.03H22.6v.726h-.737v.737h-.726v-2.189h.726v-.737h-.726v.726H20.4v.737h-.737v-1.463h-.726v1.463H18.2v.737l.737-.011h.726v1.463h2.2v.737h-2.2v.726h-.726v.726H18.2v.737h.737v.726H18.2v.737h.737v.726h.726v.726h-.726v.737H24.8V21.93h-.737v3.652H20.4V21.93h2.2v-2.915h.737v.726H24.8v-1.452h-.726v-.737h.726v-2.189h-.737v2.189zM18.2 20.478v.726h.737v-.726H18.2zm3.663-3.652v.726h.737v-.726h-.737zm1.474 3.652v.737H24.8v-.737h-1.463zm0-9.493v2.189h2.2v-2.189h-2.2zM20.4 13.9v.737h.737V13.9H20.4zm-2.937 1.463v.726h.737v-.726h-.737zm5.137 0v.726h.737v-.726H22.6zm-1.463 7.304v2.189h2.2v-2.189h-2.2zm-.737-7.304v.726h.737v-.726H20.4zm-5.137-4.389v.737H16v-.737h-.737zM20.4 9.522v.726h1.463v.726h-.737v.726H20.4v-.726h-.737v.737h.737v.715h.737v.726h.737v1.463H27V9.522h-6.6zm5.863 4.378H22.6v-3.652h3.663V13.9zM9.851 8.235c.506.341 1.078.407 1.529.429.385.022 1.034.022 1.716.022 1.265 0 2.75.022 2.904.022.407.011 1.65.011 2.75.011.682 0 1.32-.011 1.716-.022.451-.022 1.023-.099 1.529-.429.638-.429.957-1.133.957-2.09 0-.77-.319-1.232-.583-1.496-.715-.693-1.815-.649-2.178-.638h-.044c-.22 0-1.012.121-1.947.649-.825.462-1.54 1.122-2.123 1.947l-.066.165-.055-.088c-.616-.924-1.419-1.551-2.31-2.057-.924-.528-1.716-.638-1.936-.638h-.044c-.363-.011-1.463-.055-2.178.638-.484.462-.583 1.067-.583 1.496-.011.946.308 1.65.946 2.079zm8.888-2.464c.781-.451 1.375-.517 1.419-.517h.077c.627-.022 1.067.077 1.298.297.143.143.22.341.22.627 0 1.045-.495 1.276-1.342 1.32-.715.033-2.376.022-3.454.011a5.168 5.168 0 011.782-1.738zm-8.426-.253c.209-.198.583-.297 1.122-.297h.264c.044 0 .638.066 1.419.517.704.407 1.309.99 1.793 1.738-1.089.011-2.75.022-3.465-.011-.847-.044-1.342-.275-1.342-1.32 0-.286.066-.484.209-.627zm7.15 19.338h-.726v1.463h.737v-1.463h.726v-.726h-.737v.726z"/></svg>
|
Before Width: | Height: | Size: 3.4 KiB |
|
@ -1 +0,0 @@
|
|||
<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><path d="M16 0c8.837 0 16 7.163 16 16s-7.163 16-16 16S0 24.837 0 16 7.163 0 16 0zm.243 7h-.473c-.592 0-1.039.343-1.341 1.042l-2.327 5.896h-1.761c-.528.002-.956.448-.96 1v.014c.004.553.432.999.96 1.001h.946l-2.221 5.621a1.235 1.235 0 00-.066.384c0 .315.092.562.263.754.17.192.407.288.71.288a.933.933 0 00.552-.192c.17-.123.289-.302.38-.507l2.446-6.348h1.696c.527-.002.955-.449.96-1.001v-.027c-.005-.553-.433-1-.96-1.001h-.907l1.866-4.867L21.093 22.3c.092.205.21.384.381.507.161.122.354.19.553.192.302 0 .539-.096.71-.288.17-.192.262-.439.262-.754a.944.944 0 00-.065-.384l-5.35-13.532C17.28 7.342 16.834 7 16.243 7z"/></svg>
|
Before Width: | Height: | Size: 705 B |
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path fill-rule="evenodd" d="M16 32C7.163 32 0 24.837 0 16S7.163 0 16 0s16 7.163 16 16-7.163 16-16 16zM6.5 10.487v11.026L16 27l9.5-5.487V10.487L16 5l-9.5 5.487zm.912 9.97v-8.913l5.743 3.323-1.933 3.385-3.81 2.205zm.457.791l3.664-2.12 4.038 2.313v4.256l-7.702-4.449zm16.719-9.673v8.85l-3.76-2.175-1.932-3.382 5.692-3.293zm-.43-.808l-5.715 3.307-1.96-3.431V6.334l7.675 4.433zm-6.047 4.555l1.153 2.023L16.939 16l1.172-.678zm-.453-.794l-1.175.68v-2.74l1.175 2.06zm-4.864 2.815l1.151-2.02 1.17.677-2.32 1.343zm-.346 1.256l3.123-1.807v3.595L12.448 18.6zm-4.58-7.847l7.703-4.449v4.334l-1.962 3.436-5.74-3.321zm16.29 10.481l-7.675 4.433V21.47l4.04-2.34 3.635 2.103zm-4.548-2.632l-3.127 1.813v-3.622l3.127 1.81zm-5.212-4.071l1.173-2.057v2.735l-1.173-.678z"/></svg>
|
Before Width: | Height: | Size: 838 B |
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M16 32C7.163 32 0 24.837 0 16S7.163 0 16 0s16 7.163 16 16-7.163 16-16 16zM13.77 6.5a.87.87 0 00-.759.444L6.105 19.263a.87.87 0 000 .85l2.21 3.942a.87.87 0 00.758.445h13.854a.87.87 0 00.759-.445l2.209-3.942a.87.87 0 000-.85L18.989 6.944a.87.87 0 00-.759-.444h-4.46zM16 11.401l4.653 8.287h-9.306L16 11.401z"/></svg>
|
Before Width: | Height: | Size: 382 B |
|
@ -1 +0,0 @@
|
|||
<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><path d="M16 32C7.163 32 0 24.837 0 16S7.163 0 16 0s16 7.163 16 16-7.163 16-16 16zM4.406 21.711a5.525 5.525 0 00-.406.773c0 .036.144.036.295.036.34-.03.673-.103.994-.218l.441-.11a7.68 7.68 0 001.325-.738l.809-.662c.392-.318.75-.676 1.068-1.068l.883-1.253c.627-.845 1.325-1.25 2.136-1.214a3 3 0 001.325-.367l2.282-1.472a5.44 5.44 0 00.663-.48 3.12 3.12 0 00-.406-.736l-.441-.735c-.478-.773-.478-.811-.036-1.62l.036-.11a6.22 6.22 0 00.37-.737 4.414 4.414 0 00-.15-1.078 2.136 2.136 0 00-.292.48c-.406.845-.663 1.325-.701 1.325-.11 0-.036-1.032.185-1.656l.993-3.12c.257-.921.295-.921.552 0l1.469 4.601c.187.626.336.737.96.737h1.03c.808-.039 1.322.331 1.73 1.214.222.39.495.75.811 1.068l5.117 5.309c.162.201.348.383.552.542v-.036c-.126-.225-.26-.446-.403-.662l-3.792-5.448c-.29-.416-.611-.81-.96-1.178l-1.176-1.25a1.853 1.853 0 00-1.253-.553h-.293c-.921 0-1.805-.662-2.172-1.584l-1.62-4.013A1.982 1.982 0 0015.964 5c-.191.197-.353.42-.48.662l-3.749 5.744a.703.703 0 01-.993.292h-.039c-.372-.22-.739-.11-.96.296L4.406 21.71z"/></svg>
|
Before Width: | Height: | Size: 1.1 KiB |
|
@ -1 +0,0 @@
|
|||
<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><path d="M16 32C7.163 32 0 24.837 0 16S7.163 0 16 0s16 7.163 16 16-7.163 16-16 16zm-.275-25.94c-.39.152-.49.707-.186.988.287.293.847.19.995-.193.255-.471-.33-1.042-.81-.796zm-5.155.546c-.405.106-.45.734-.057.884.297.16.718-.089.687-.427.03-.313-.339-.575-.63-.457zm10.558.893c.31.078.54-.17.612-.44-.05-.317-.362-.622-.701-.46-.438.142-.366.846.089.9zm-9.385 1.265c-.456.23-.519.914-.105 1.212.428.38 1.186.054 1.211-.507.075-.557-.62-1.008-1.106-.705zm7.43.322c-.271.536.276 1.15.853 1.044.435-.142.736-.659.491-1.076-.247-.536-1.127-.519-1.344.032zm-4.069 1.013c-.026.386.255.702.588.863.218.013.455.054.655-.056.438-.19.654-.762.411-1.178-.13-.3-.46-.428-.763-.488-.458.033-.896.385-.891.859zm-7.666.69c-.388.175-.442.766-.1 1.012.322.262.884.095.976-.316.169-.475-.431-.966-.876-.697zm16.462-.002c-.388.234-.345.858.067 1.04.374.22.913-.102.887-.529.045-.468-.577-.799-.954-.51zm-6.64.851c-.776.232-1.236 1.158-.92 1.898.278.827 1.377 1.211 2.13.758.725-.383.974-1.4.506-2.067-.354-.546-1.094-.81-1.716-.589zm-3.653.073c-.735.323-1.073 1.276-.692 1.978.34.725 1.33 1.023 2.032.63.701-.349 1.004-1.29.612-1.966-.333-.694-1.262-.963-1.952-.642zM9.95 12.94c-.101.514.365 1.036.898.99.484.003.837-.436.867-.885a.978.978 0 00-.87-.857c-.423.03-.842.315-.895.752zm10.802-.656c-.587.272-.63 1.172-.065 1.492.544.384 1.384-.077 1.347-.732.024-.618-.735-1.073-1.282-.76zm-8.63 2.307c-.868.206-1.376 1.256-.958 2.039.365.854 1.626 1.106 2.31.48.534-.427.674-1.236.331-1.818-.314-.578-1.045-.874-1.684-.701zm6.927-.003c-.874.235-1.336 1.325-.877 2.096.38.746 1.447.996 2.136.52.657-.411.868-1.362.426-1.999-.334-.557-1.064-.792-1.685-.617zm-11.04.726c-.53.148-.687.904-.262 1.243.363.362 1.066.18 1.203-.31.223-.539-.389-1.138-.941-.933zm14.969.782c.092.21.203.43.42.538.464.251 1.119-.112 1.084-.647.03-.406-.338-.706-.716-.765a.836.836 0 00-.788.874zM5.294 15.58c-.275.123-.394.49-.194.729.226.343.843.185.86-.226.077-.363-.334-.646-.666-.503zm20.949-.009c-.39.205-.237.912.235.87.336.05.624-.353.467-.647-.093-.269-.468-.386-.702-.223zm-12.317 1.973c-.654.14-1.158.751-1.156 1.409-.023.687.52 1.343 1.212 1.453.895.206 1.82-.587 1.763-1.482-.005-.886-.945-1.603-1.82-1.38zm3.462-.001c-.526.128-.972.555-1.088 1.08-.23.787.378 1.678 1.203 1.783.876.174 1.773-.593 1.726-1.471.014-.906-.954-1.636-1.84-1.392zm-6.676.545c-.663.066-1.013.943-.545 1.422.4.5 1.304.334 1.486-.278.249-.573-.327-1.247-.94-1.144zm10.154.027c-.661.207-.772 1.2-.165 1.536.535.376 1.365-.068 1.343-.711.042-.585-.63-1.05-1.178-.825zm2.838 2.8c.145.398.75.493 1.017.16.197-.179.148-.457.119-.69-.141-.144-.296-.315-.517-.311-.444-.073-.833.448-.619.841zm-16.268-.732c-.395.198-.409.817-.027 1.034.356.24.896-.001.945-.423.094-.477-.503-.882-.918-.61zm8.193.883c-.654.207-.752 1.193-.163 1.528.531.39 1.387-.06 1.346-.71.052-.588-.64-1.053-1.183-.818zm-3.794.871c-.326.12-.459.474-.465.791.112.291.338.598.685.605.42.062.834-.294.82-.712.042-.51-.578-.923-1.04-.684zm7.686.008c-.464.233-.516.937-.088 1.23.443.374 1.207.01 1.195-.56.045-.544-.631-.96-1.107-.67zm1.337 3.25c.217.366.85.236.891-.19.058-.316-.234-.52-.51-.575-.344.072-.593.451-.381.766zm-10.611-.273c.03.359.428.67.77.443.381-.2.252-.845-.183-.875-.299-.065-.503.183-.587.432zm5.12.287c-.153.373.213.824.618.777.218.005.387-.148.518-.3.025-.103.051-.207.08-.31-.054-.198-.116-.43-.328-.52-.32-.196-.805-.016-.889.353z"/></svg>
|
Before Width: | Height: | Size: 3.4 KiB |
|
@ -1 +0,0 @@
|
|||
<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><path d="M16 32C7.163 32 0 24.837 0 16S7.163 0 16 0s16 7.163 16 16-7.163 16-16 16zm8.984-14.369h-4.928l-.88-2.64h5.8a.748.748 0 100-1.496H18.7l-2.517-7.673a1.074 1.074 0 00-2.12-.07l-6.02 18.303c-.016.1-.016.2 0 .3a1.012 1.012 0 001.989.246l5.051-15.4 1.443 4.294h-1.25a.748.748 0 100 1.496h1.76l.88 2.64h-2.64a.748.748 0 100 1.496h3.16l1.425 4.224h-7.559a1.056 1.056 0 100 2.112h8.941c.554 0 1.003-.449 1.003-1.003a1.03 1.03 0 00-.097-.44l-1.61-4.893h4.4a.748.748 0 100-1.496h.044z"/></svg>
|
Before Width: | Height: | Size: 574 B |
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill-rule="evenodd" d="M16 32C7.163 32 0 24.837 0 16S7.163 0 16 0s16 7.163 16 16-7.163 16-16 16zM11.587 8.602L9 11.36l4.36 4.614L9 20.68l2.587 2.717L16 18.792l4.305 4.604L23 20.603l-4.396-4.604L23 11.36l-2.695-2.757L16 13.208l-4.413-4.606zm.355-.376l2.126 2.265 1.914-2.114 1.914 2.114 2.126-2.265L15.982 4l-4.04 4.226zm0 15.548L15.982 28l4.04-4.226-2.126-2.265-1.914 2.114-1.914-2.114-2.126 2.265z"/></svg>
|
Before Width: | Height: | Size: 473 B |
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill-rule="evenodd" d="M16 32C7.163 32 0 24.837 0 16S7.163 0 16 0s16 7.163 16 16-7.163 16-16 16zM9.752 11c-2.473.174-4.591 2.228-4.752 4.621v.785c.17 2.398 2.317 4.428 4.787 4.594h.803c1.96-.172 3.608-1.415 4.796-2.862-.29-.425-.583-.849-.884-1.266-.764 1.128-1.76 2.192-3.102 2.66-1.208.438-2.61.157-3.615-.596-1.342-.95-1.83-2.793-1.23-4.279.682-1.804 2.97-2.866 4.843-2.187 1.515.551 2.45 1.915 3.366 3.128 1.064 1.372 1.944 2.913 3.315 4.036.944.802 2.156 1.266 3.403 1.366h.746c2.026-.18 3.879-1.534 4.515-3.417a60.387 60.387 0 00-1.389.006c-.908 1.854-3.493 2.751-5.341 1.654-2.557-1.517-3.661-4.394-5.67-6.432-.968-.99-2.274-1.677-3.687-1.811h-.904zm11.68 0c-1.974.183-3.61 1.453-4.783 2.921.275.407.559.809.845 1.207.743-1.075 1.707-2.081 2.987-2.54 1.606-.61 3.615-.035 4.565 1.37.39.538.54 1.189.654 1.825-1.624.01-3.247 0-4.873.004.002.36.002.717 0 1.077 2.057-.002 4.116.01 6.173-.009v-1.23c-.205-2.397-2.325-4.468-4.818-4.625h-.75z"/></svg>
|
Before Width: | Height: | Size: 1019 B |
|
@ -1 +0,0 @@
|
|||
<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><path d="M16 32C7.163 32 0 24.837 0 16S7.163 0 16 0s16 7.163 16 16-7.163 16-16 16zm10.965-17.29c-.328-2.964-5.51-4.798-11.57-4.095-6.06.702-10.706 3.675-10.378 6.64.329 2.964 5.507 4.797 11.57 4.095 6.065-.703 10.707-3.676 10.378-6.64zm-6.34 1.484c-.614.438-1.509.654-2.684.659l-1.141.004-.035.163a.434.434 0 00-.017.11c-.005.023-.005.045-.005.063 0 .252.117.437.346.56.23.129.57.19 1.016.19.423 0 .83-.048 1.214-.136.38-.089.748-.221 1.098-.398l-.29 1.555c-.436.106-.855.19-1.27.243a8.807 8.807 0 01-1.206.089c-.553 0-1.011-.067-1.379-.208-.38-.146-.804-.464-1.015-.919a4.641 4.641 0 01-1.34.892 3.684 3.684 0 01-1.453.296c-.63.005-1.128-.15-1.482-.455-.359-.304-.536-.729-.54-1.263-.005-.822.302-1.445.912-1.878.613-.437 1.508-.653 2.684-.658l1.14-.004.035-.164a.434.434 0 00.018-.11c.004-.022.004-.044.004-.062 0-.252-.117-.437-.346-.561-.229-.128-.57-.19-1.016-.19-.423 0-.83.049-1.214.137-.38.088-.748.22-1.098.398l.29-1.555c.436-.106.855-.19 1.27-.243a8.807 8.807 0 011.206-.089c.554 0 1.012.067 1.38.208.38.146.803.464 1.015.919a4.641 4.641 0 011.34-.893 3.684 3.684 0 011.452-.296c.631-.004 1.128.15 1.482.455.36.305.536.73.54 1.264.005.817-.297 1.444-.911 1.877zm-6.626.128c-.497 0-.873.084-1.133.243-.25.155-.376.39-.376.698 0 .23.078.416.225.548.151.133.363.199.627.199.41 0 .752-.128 1.024-.38.273-.256.458-.614.55-1.073l.042-.235h-.96zm5.264-2.169c-.151-.132-.363-.198-.626-.198-.411 0-.753.128-1.025.38-.272.256-.458.614-.549 1.073l-.043.234.96-.004c.497 0 .873-.084 1.132-.243.25-.155.376-.389.376-.698 0-.23-.073-.411-.225-.544zm-2.74 7.55c-.877.102-1.746.15-2.589.15-2.006 0-3.881-.282-5.442-.835a8.81 8.81 0 01-1.84-.883c-.213 1.118-.07 2.103.479 2.836 1.577 2.107 5.99 1.436 10.356-1.4-.32.048-.64.092-.964.132zm-1.024-11.397c2.96-.345 5.813-.102 8.03.684a8.81 8.81 0 011.842.884c.211-1.118.069-2.103-.48-2.836-1.578-2.107-5.99-1.436-10.356 1.4.32-.053.644-.097.964-.132zm-3.22 13.96a9.094 9.094 0 01-1.76.242c.446 1.18 1.142 2.006 2.062 2.315 2.222.747 5.096-1.7 7.132-5.752-.48.133-.977.252-1.478.354-1.989 1.405-4.063 2.399-5.956 2.84zm7.598-16.554a9.044 9.044 0 011.76-.234c-.442-1.18-1.133-2.01-2.054-2.323-2.217-.756-5.104 1.678-7.153 5.716.48-.132.977-.247 1.482-.344 1.989-1.4 4.068-2.382 5.965-2.815z"/></svg>
|
Before Width: | Height: | Size: 2.3 KiB |
|
@ -1 +0,0 @@
|
|||
<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><path d="M16 32C7.163 32 0 24.837 0 16S7.163 0 16 0s16 7.163 16 16-7.163 16-16 16zm-.048-13.014a7.144 7.144 0 00.093 0 .055.055 0 01.004.014.049.049 0 11-.097-.014zm-6.014-3.493a6.993 6.993 0 006.055 10.493 7.002 7.002 0 006.993-6.993 6.96 6.96 0 00-.94-3.503 6.993 6.993 0 10-12.11.003zM16.048 12a7.138 7.138 0 00-.097 0 .049.049 0 01.049-.05.055.055 0 01.049.05z"/></svg>
|
Before Width: | Height: | Size: 456 B |
|
@ -1 +0,0 @@
|
|||
<svg height="32" viewBox="0 0 32 32" width="32" xmlns="http://www.w3.org/2000/svg"><path d="M16 32C7.163 32 0 24.837 0 16S7.163 0 16 0s16 7.163 16 16-7.163 16-16 16zm1.144-25.576c.502.483.956 1.01 1.356 1.576a5.047 5.047 0 01-.125 5.273.627.627 0 00.063.727c.214.29.624.37.937.182 1.188-.97 1.25-3.03 1.313-3.455a4.497 4.497 0 00-.188-1.272 6.463 6.463 0 00-.5-1.152 3.709 3.709 0 00-.75-.97 5.63 5.63 0 00-1.875-1.272.289.289 0 00-.313 0 .28.28 0 00.082.363zM15.3 25.006c-.51-.481-.97-1.01-1.375-1.576a5.047 5.047 0 01.125-5.272.539.539 0 000-.728.714.714 0 00-.938-.182c-1.187.97-1.25 3.03-1.312 3.455 0 .43.064.86.188 1.273.128.398.295.784.5 1.151.193.361.446.689.75.97a5.63 5.63 0 001.875 1.273c.062.06.187 0 .25-.06s.062-.183-.063-.304zm5.394-5a5.473 5.473 0 00-1.313-3.151 10.816 10.816 0 00-2.625-1.94 14.466 14.466 0 01-2.375-1.642 4.032 4.032 0 01-1.187-2.121 4.243 4.243 0 01.306-2.48 6.692 6.692 0 011.756-2.242.26.26 0 00.063-.303.242.242 0 00-.375-.06 5.577 5.577 0 00-2.438 2.06 5.01 5.01 0 00-.881 3.273 5.25 5.25 0 00.438 1.697 6 6 0 001 1.455 10.78 10.78 0 002.687 1.878c.848.44 1.645.969 2.375 1.576a3.603 3.603 0 011.188 2.182c.176.879.066 1.79-.313 2.606a6.13 6.13 0 01-1.813 2.182.207.207 0 00-.063.303c.035.064.1.11.173.121s.149-.01.203-.06a7.801 7.801 0 002.375-2.122c.62-.958.906-2.084.819-3.212z"/><path d="M17.144 6.424a.28.28 0 01-.081-.363.289.289 0 01.312 0 5.63 5.63 0 011.875 1.272c.303.281.557.609.75.97.204.368.371.753.5 1.152.123.413.187.842.188 1.272-.063.425-.125 2.485-1.313 3.455a.714.714 0 01-.938-.182.627.627 0 01-.062-.727A5.047 5.047 0 0018.5 8c-.4-.566-.854-1.093-1.356-1.576zM15.3 25.006c.125.121.125.242.063.303s-.188.121-.25.06a5.63 5.63 0 01-1.875-1.272 3.709 3.709 0 01-.75-.97 6.463 6.463 0 01-.5-1.151 4.482 4.482 0 01-.188-1.273c.063-.424.125-2.485 1.313-3.455a.714.714 0 01.937.182.539.539 0 010 .728 5.047 5.047 0 00-.125 5.272c.405.567.866 1.095 1.375 1.576z" fill-opacity=".5"/></svg>
|
Before Width: | Height: | Size: 1.9 KiB |
|
@ -1 +0,0 @@
|
|||
<svg height="32" viewBox="0 0 32 32" width="32" xmlns="http://www.w3.org/2000/svg"><path d="M16 32C7.163 32 0 24.837 0 16S7.163 0 16 0s16 7.163 16 16-7.163 16-16 16zm3.755-14.666C22.001 13.815 23.75 8 23.75 8l-3.745.849-1.371 4.85c-.129-3.636-2.622-4.967-2.622-4.967-1.997-.973-3.777-.545-5.06.124-1.588.826-2.743 2.266-3.296 3.924-.786 2.359-.69 5.006-.586 6.204.042.562.166 1.115.37 1.643 1.378 3.573 5.195 3.37 5.195 3.37 3.497-.124 5.622-4.242 5.622-4.242l1.002 3.028c.898 1.519 2.887.95 3.296.865.072-.016.136-.024.209-.04L25 23.267v-.973c-4.868.132-5.245-4.959-5.245-4.959zm-4.739 3.659a2.369 2.369 0 01-1.098.638c-.907.226-1.604-.155-2.085-.622a3.937 3.937 0 01-1.059-1.978c-.882-4.99.337-7.177 1.147-8.182a2.258 2.258 0 011.868-.864c3.144.164 3.85 6.742 3.85 6.742-.89 2.335-2.037 3.69-2.623 4.266z" fill-rule="evenodd"/></svg>
|
Before Width: | Height: | Size: 835 B |
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M16 32C7.163 32 0 24.837 0 16S7.163 0 16 0s16 7.163 16 16-7.163 16-16 16zm-.029-8.85c3.957 0 7.176-3.199 7.176-7.13 0-3.932-3.219-7.13-7.176-7.13-3.957 0-7.176 3.198-7.176 7.13 0 3.931 3.22 7.13 7.176 7.13zm0-12.864c3.182 0 5.77 2.572 5.77 5.734 0 3.161-2.588 5.733-5.77 5.733-3.181 0-5.77-2.572-5.77-5.733 0-3.162 2.589-5.734 5.77-5.734zm5.025-2.415l.736-1.19a11.053 11.053 0 00-5.76-1.614c-1.874 0-3.724.476-5.35 1.375l.683 1.221a9.67 9.67 0 014.666-1.198c1.78 0 3.517.486 5.025 1.406zm2.095 16.51a10.911 10.911 0 003.902-8.361h-1.406a9.519 9.519 0 01-3.405 7.294l.909 1.067zm-7.12 2.59c1.762 0 3.516-.423 5.07-1.224l-.648-1.24a9.558 9.558 0 01-4.422 1.068 9.667 9.667 0 01-6.12-2.185l-.896 1.076a11.083 11.083 0 007.016 2.506zm9.38-13.546l1.128-.31a10.71 10.71 0 00-2.125-4.026l-.9.745a9.558 9.558 0 011.897 3.591zM6.86 21.976l.978-.64a9.587 9.587 0 01-1.601-5.316 9.564 9.564 0 012.966-6.952l-.814-.837a10.717 10.717 0 00-3.323 7.789c0 2.127.62 4.187 1.793 5.956z"/><path d="M25.35 13.425a9.558 9.558 0 00-1.896-3.59l.9-.746a10.71 10.71 0 012.125 4.025l-1.128.311zM6.86 21.976a10.742 10.742 0 01-1.793-5.956c0-2.962 1.18-5.728 3.323-7.789l.814.837a9.564 9.564 0 00-2.966 6.952c0 1.899.554 3.737 1.6 5.316l-.978.64z" opacity=".5"/></svg>
|
Before Width: | Height: | Size: 1.3 KiB |