mirror of
https://github.com/basicswap/basicswap.git
synced 2025-04-06 14:27:30 +00:00
commit
aa9babdc69
28 changed files with 849 additions and 1012 deletions
basicswap
basicswap.py
bin
chainparams.pyconfig.pyinterface
pgp/keys
bitcoincash_Calin_Culianu.pgpnamecoin_JeremyRand.pgpnamecoin_RoseTuring.pgpparticl_tecnovert.pgpwownero_wowario.pgp
static
images/coins
js
templates
tests/basicswap
|
@ -391,7 +391,7 @@ class BasicSwap(BaseApp):
|
|||
Coins.PART_BLIND,
|
||||
Coins.BCH,
|
||||
)
|
||||
self.coins_without_segwit = (Coins.PIVX, Coins.DASH, Coins.NMC)
|
||||
self.coins_without_segwit = (Coins.PIVX, Coins.DASH)
|
||||
|
||||
# TODO: Adjust ranges
|
||||
self.min_delay_event = self.get_int_setting("min_delay_event", 10, 0, 20 * 60)
|
||||
|
|
|
@ -52,11 +52,17 @@ PARTICL_VERSION = os.getenv("PARTICL_VERSION", "23.2.7.0")
|
|||
PARTICL_VERSION_TAG = os.getenv("PARTICL_VERSION_TAG", "")
|
||||
PARTICL_LINUX_EXTRA = os.getenv("PARTICL_LINUX_EXTRA", "nousb")
|
||||
|
||||
BITCOIN_VERSION = os.getenv("BITCOIN_VERSION", "28.0")
|
||||
BITCOIN_VERSION_TAG = os.getenv("BITCOIN_VERSION_TAG", "")
|
||||
|
||||
LITECOIN_VERSION = os.getenv("LITECOIN_VERSION", "0.21.4")
|
||||
LITECOIN_VERSION_TAG = os.getenv("LITECOIN_VERSION_TAG", "")
|
||||
|
||||
BITCOIN_VERSION = os.getenv("BITCOIN_VERSION", "28.0")
|
||||
BITCOIN_VERSION_TAG = os.getenv("BITCOIN_VERSION_TAG", "")
|
||||
DCR_VERSION = os.getenv("DCR_VERSION", "1.8.1")
|
||||
DCR_VERSION_TAG = os.getenv("DCR_VERSION_TAG", "")
|
||||
|
||||
NMC_VERSION = os.getenv("NMC_VERSION", "28.0")
|
||||
NMC_VERSION_TAG = os.getenv("NMC_VERSION_TAG", "")
|
||||
|
||||
MONERO_VERSION = os.getenv("MONERO_VERSION", "0.18.3.4")
|
||||
MONERO_VERSION_TAG = os.getenv("MONERO_VERSION_TAG", "")
|
||||
|
@ -82,9 +88,6 @@ FIRO_VERSION_TAG = os.getenv("FIRO_VERSION_TAG", "")
|
|||
NAV_VERSION = os.getenv("NAV_VERSION", "7.0.3")
|
||||
NAV_VERSION_TAG = os.getenv("NAV_VERSION_TAG", "")
|
||||
|
||||
DCR_VERSION = os.getenv("DCR_VERSION", "1.8.1")
|
||||
DCR_VERSION_TAG = os.getenv("DCR_VERSION_TAG", "")
|
||||
|
||||
BITCOINCASH_VERSION = os.getenv("BITCOINCASH_VERSION", "28.0.1")
|
||||
BITCOINCASH_VERSION_TAG = os.getenv("BITCOINCASH_VERSION_TAG", "")
|
||||
|
||||
|
@ -103,7 +106,7 @@ known_coins = {
|
|||
"bitcoin": (BITCOIN_VERSION, BITCOIN_VERSION_TAG, ("laanwj",)),
|
||||
"litecoin": (LITECOIN_VERSION, LITECOIN_VERSION_TAG, ("davidburkett38",)),
|
||||
"decred": (DCR_VERSION, DCR_VERSION_TAG, ("decred_release",)),
|
||||
"namecoin": ("0.18.0", "", ("JeremyRand",)),
|
||||
"namecoin": (NMC_VERSION, NMC_VERSION_TAG, ("RoseTuring",)),
|
||||
"monero": (MONERO_VERSION, MONERO_VERSION_TAG, ("binaryfate",)),
|
||||
"wownero": (WOWNERO_VERSION, WOWNERO_VERSION_TAG, ("wowario",)),
|
||||
"pivx": (PIVX_VERSION, PIVX_VERSION_TAG, ("fuzzbawls",)),
|
||||
|
@ -116,26 +119,32 @@ known_coins = {
|
|||
|
||||
disabled_coins = [
|
||||
"navcoin",
|
||||
"namecoin", # Needs update
|
||||
]
|
||||
|
||||
expected_key_ids = {
|
||||
"tecnovert": ("13F13651C9CF0D6B",),
|
||||
"thrasher": ("FE3348877809386C",),
|
||||
"laanwj": ("1E4AED62986CD25D",),
|
||||
"JeremyRand": ("2DBE339E29F6294C",),
|
||||
"binaryfate": ("F0AF4D462A0BDF92",),
|
||||
"wowario": ("793504B449C69220",),
|
||||
"davidburkett38": ("3620E9D387E55666",),
|
||||
"xanimo": ("6E8F17C1B1BCDCBE",),
|
||||
"patricklodder": ("2D3A345B98D0DC1F",),
|
||||
"fuzzbawls": ("C1ABA64407731FD9",),
|
||||
"pasta": ("52527BEDABE87984", "E2F3D7916E722D38"),
|
||||
"reuben": ("1290A1D0FA7EE109",),
|
||||
"nav_builder": ("2782262BF6E7FADB",),
|
||||
"nicolasdorier": ("6618763EF09186FE", "223FDA69DEBEA82D", "62FE85647DEDDA2E"),
|
||||
"decred_release": ("6D897EDF518A031D",),
|
||||
"Calin_Culianu": ("21810A542031C02C",),
|
||||
"tecnovert": ("8E517DC12EC1CC37F6423A8A13F13651C9CF0D6B",),
|
||||
"thrasher": ("59CAF0E96F23F53747945FD4FE3348877809386C",),
|
||||
"laanwj": ("9DEAE0DC7063249FB05474681E4AED62986CD25D",),
|
||||
"RoseTuring": ("FD8366A807A99FA27FD9CCEA9FE3BFDDA6C53495",),
|
||||
"binaryfate": ("81AC591FE9C4B65C5806AFC3F0AF4D462A0BDF92",),
|
||||
"wowario": ("AB3A2F725818FCFF2794841C793504B449C69220",),
|
||||
"davidburkett38": ("D35621D53A1CC6A3456758D03620E9D387E55666",),
|
||||
"xanimo": ("2EAA8B1021C71AD5186CA07F6E8F17C1B1BCDCBE",),
|
||||
"patricklodder": ("DC6EF4A8BF9F1B1E4DE1EE522D3A345B98D0DC1F",),
|
||||
"fuzzbawls": ("0CFBDA9F60D661BA31EB5D50C1ABA64407731FD9",),
|
||||
"pasta": (
|
||||
"29590362EC878A81FD3C202B52527BEDABE87984",
|
||||
"02B8E7D002167C8B451AF05FE2F3D7916E722D38",
|
||||
),
|
||||
"reuben": ("0186454D63E83D85EF91DE4E1290A1D0FA7EE109",),
|
||||
"nav_builder": ("1BF9B51BAED51BA0B3A174EE2782262BF6E7FADB",),
|
||||
"nicolasdorier": (
|
||||
"AB4CFA9895ACA0DBE27F6B346618763EF09186FE",
|
||||
"015B4C837B245509E4AC8995223FDA69DEBEA82D",
|
||||
"7121BDE3555D9BE06BDDC68162FE85647DEDDA2E",
|
||||
),
|
||||
"decred_release": ("F516ADB7A069852C7C28A02D6D897EDF518A031D",),
|
||||
"Calin_Culianu": ("D465135F97D0047E18E99DC321810A542031C02C",),
|
||||
}
|
||||
|
||||
USE_PLATFORM = os.getenv("USE_PLATFORM", platform.system())
|
||||
|
@ -181,6 +190,36 @@ PART_ONION_PORT = int(os.getenv("PART_ONION_PORT", 51734))
|
|||
PART_RPC_USER = os.getenv("PART_RPC_USER", "")
|
||||
PART_RPC_PWD = os.getenv("PART_RPC_PWD", "")
|
||||
|
||||
BTC_RPC_HOST = os.getenv("BTC_RPC_HOST", "127.0.0.1")
|
||||
BTC_RPC_PORT = int(os.getenv("BTC_RPC_PORT", 19996))
|
||||
BTC_PORT = int(os.getenv("BTC_PORT", 8333))
|
||||
BTC_ONION_PORT = int(os.getenv("BTC_ONION_PORT", 8334))
|
||||
BTC_RPC_USER = os.getenv("BTC_RPC_USER", "")
|
||||
BTC_RPC_PWD = os.getenv("BTC_RPC_PWD", "")
|
||||
|
||||
LTC_RPC_HOST = os.getenv("LTC_RPC_HOST", "127.0.0.1")
|
||||
LTC_RPC_PORT = int(os.getenv("LTC_RPC_PORT", 19895))
|
||||
LTC_ONION_PORT = int(os.getenv("LTC_ONION_PORT", 9333))
|
||||
LTC_RPC_USER = os.getenv("LTC_RPC_USER", "")
|
||||
LTC_RPC_PWD = os.getenv("LTC_RPC_PWD", "")
|
||||
|
||||
DCR_RPC_HOST = os.getenv("DCR_RPC_HOST", "127.0.0.1")
|
||||
DCR_RPC_PORT = int(os.getenv("DCR_RPC_PORT", 9109))
|
||||
DCR_WALLET_RPC_HOST = os.getenv("DCR_WALLET_RPC_HOST", "127.0.0.1")
|
||||
DCR_WALLET_RPC_PORT = int(os.getenv("DCR_WALLET_RPC_PORT", 9209))
|
||||
DCR_WALLET_PWD = os.getenv(
|
||||
"DCR_WALLET_PWD", random.randbytes(random.randint(14, 18)).hex()
|
||||
)
|
||||
DCR_RPC_USER = os.getenv("DCR_RPC_USER", "user")
|
||||
DCR_RPC_PWD = os.getenv("DCR_RPC_PWD", random.randbytes(random.randint(14, 18)).hex())
|
||||
|
||||
NMC_RPC_HOST = os.getenv("NMC_RPC_HOST", "127.0.0.1")
|
||||
NMC_RPC_PORT = int(os.getenv("NMC_RPC_PORT", 19698))
|
||||
NMC_PORT = int(os.getenv("NMC_PORT", 8134))
|
||||
NMC_ONION_PORT = int(os.getenv("NMC_ONION_PORT", 9698))
|
||||
NMC_RPC_USER = os.getenv("NMC_RPC_USER", "")
|
||||
NMC_RPC_PWD = os.getenv("NMC_RPC_PWD", "")
|
||||
|
||||
XMR_RPC_HOST = os.getenv("XMR_RPC_HOST", "127.0.0.1")
|
||||
XMR_RPC_PORT = int(os.getenv("XMR_RPC_PORT", 29798))
|
||||
XMR_ZMQ_PORT = int(os.getenv("XMR_ZMQ_PORT", 30898))
|
||||
|
@ -203,32 +242,6 @@ WOW_RPC_USER = os.getenv("WOW_RPC_USER", "")
|
|||
WOW_RPC_PWD = os.getenv("WOW_RPC_PWD", "")
|
||||
DEFAULT_WOW_RESTORE_HEIGHT = int(os.getenv("DEFAULT_WOW_RESTORE_HEIGHT", 450000))
|
||||
|
||||
LTC_RPC_HOST = os.getenv("LTC_RPC_HOST", "127.0.0.1")
|
||||
LTC_RPC_PORT = int(os.getenv("LTC_RPC_PORT", 19895))
|
||||
LTC_ONION_PORT = int(os.getenv("LTC_ONION_PORT", 9333))
|
||||
LTC_RPC_USER = os.getenv("LTC_RPC_USER", "")
|
||||
LTC_RPC_PWD = os.getenv("LTC_RPC_PWD", "")
|
||||
|
||||
BTC_RPC_HOST = os.getenv("BTC_RPC_HOST", "127.0.0.1")
|
||||
BTC_RPC_PORT = int(os.getenv("BTC_RPC_PORT", 19996))
|
||||
BTC_PORT = int(os.getenv("BTC_PORT", 8333))
|
||||
BTC_ONION_PORT = int(os.getenv("BTC_ONION_PORT", 8334))
|
||||
BTC_RPC_USER = os.getenv("BTC_RPC_USER", "")
|
||||
BTC_RPC_PWD = os.getenv("BTC_RPC_PWD", "")
|
||||
|
||||
DCR_RPC_HOST = os.getenv("DCR_RPC_HOST", "127.0.0.1")
|
||||
DCR_RPC_PORT = int(os.getenv("DCR_RPC_PORT", 9109))
|
||||
DCR_WALLET_RPC_HOST = os.getenv("DCR_WALLET_RPC_HOST", "127.0.0.1")
|
||||
DCR_WALLET_RPC_PORT = int(os.getenv("DCR_WALLET_RPC_PORT", 9209))
|
||||
DCR_WALLET_PWD = os.getenv(
|
||||
"DCR_WALLET_PWD", random.randbytes(random.randint(14, 18)).hex()
|
||||
)
|
||||
DCR_RPC_USER = os.getenv("DCR_RPC_USER", "user")
|
||||
DCR_RPC_PWD = os.getenv("DCR_RPC_PWD", random.randbytes(random.randint(14, 18)).hex())
|
||||
|
||||
NMC_RPC_HOST = os.getenv("NMC_RPC_HOST", "127.0.0.1")
|
||||
NMC_RPC_PORT = int(os.getenv("NMC_RPC_PORT", 19698))
|
||||
|
||||
PIVX_RPC_HOST = os.getenv("PIVX_RPC_HOST", "127.0.0.1")
|
||||
PIVX_RPC_PORT = int(os.getenv("PIVX_RPC_PORT", 51473))
|
||||
PIVX_ONION_PORT = int(os.getenv("PIVX_ONION_PORT", 51472)) # nDefaultPort
|
||||
|
@ -375,6 +388,12 @@ def getWalletName(coin_params: str, default_name: str, prefix_override=None) ->
|
|||
return wallet_name
|
||||
|
||||
|
||||
def getDescriptorWalletOption(coin_params):
|
||||
ticker: str = coin_params["ticker"]
|
||||
default_option: bool = True if ticker in ("NMC",) else False
|
||||
return toBool(os.getenv(ticker + "_USE_DESCRIPTORS", default_option))
|
||||
|
||||
|
||||
def getKnownVersion(coin_name: str) -> str:
|
||||
version, version_tag, _ = known_coins[coin_name]
|
||||
return version + version_tag
|
||||
|
@ -528,7 +547,7 @@ def testOnionLink():
|
|||
|
||||
def havePubkey(gpg, key_id):
|
||||
for key in gpg.list_keys():
|
||||
if key["keyid"] == key_id:
|
||||
if key["fingerprint"] == key_id:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
@ -591,8 +610,10 @@ def ensureValidSignatureBy(result, signing_key_name):
|
|||
if not isValidSignature(result):
|
||||
raise ValueError("Signature verification failed.")
|
||||
|
||||
if result.key_id not in expected_key_ids[signing_key_name]:
|
||||
raise ValueError("Signature made by unexpected keyid: " + result.key_id)
|
||||
if result.fingerprint not in expected_key_ids[signing_key_name]:
|
||||
raise ValueError(
|
||||
"Signature made by unexpected key fingerprint: " + result.fingerprint
|
||||
)
|
||||
|
||||
logger.debug(f"Found valid signature by {signing_key_name} ({result.key_id}).")
|
||||
|
||||
|
@ -931,16 +952,10 @@ def prepareCore(coin, version_data, settings, data_dir, extra_opts={}):
|
|||
% (version, assert_filename)
|
||||
)
|
||||
elif coin == "namecoin":
|
||||
release_url = "https://beta.namecoin.org/files/namecoin-core/namecoin-core-{}/{}".format(
|
||||
version, release_filename
|
||||
)
|
||||
assert_filename = "{}-{}-{}-build.assert".format(
|
||||
coin, os_name, version.rsplit(".", 1)[0]
|
||||
)
|
||||
assert_url = (
|
||||
"https://raw.githubusercontent.com/namecoin/gitian.sigs/master/%s-%s/%s/%s"
|
||||
% (version, os_dir_name, signing_key_name, assert_filename)
|
||||
)
|
||||
release_url = f"https://www.namecoin.org/files/namecoin-core/namecoin-core-{version}/{release_filename}"
|
||||
signing_key = "Rose%20Turing"
|
||||
assert_filename = "noncodesigned.SHA256SUMS"
|
||||
assert_url = f"https://raw.githubusercontent.com/namecoin/guix.sigs/main/{version}/{signing_key}/{assert_filename}"
|
||||
elif coin == "pivx":
|
||||
release_filename = "{}-{}-{}.{}".format(coin, version, BIN_ARCH, FILE_EXT)
|
||||
release_url = (
|
||||
|
@ -1345,6 +1360,8 @@ def prepareDataDir(coin, settings, chain, particl_mnemonic, extra_opts={}):
|
|||
fp.write("printtoconsole=0\n")
|
||||
fp.write("daemon=0\n")
|
||||
fp.write(f"wallet={wallet_name}\n")
|
||||
if "watch_wallet_name" in core_settings:
|
||||
fp.write("wallet={}\n".format(core_settings["watch_wallet_name"]))
|
||||
|
||||
if tor_control_password is not None:
|
||||
writeTorSettings(fp, coin, core_settings, tor_control_password)
|
||||
|
@ -1401,6 +1418,10 @@ def prepareDataDir(coin, settings, chain, particl_mnemonic, extra_opts={}):
|
|||
)
|
||||
elif coin == "namecoin":
|
||||
fp.write("prune=2000\n")
|
||||
fp.write("deprecatedrpc=create_bdb\n")
|
||||
fp.write("addresstype=bech32\n")
|
||||
fp.write("changetype=bech32\n")
|
||||
fp.write("fallbackfee=0.001\n") # minrelaytxfee
|
||||
elif coin == "pivx":
|
||||
params_dir = os.path.join(data_dir, "pivx-params")
|
||||
downloadPIVXParams(params_dir)
|
||||
|
@ -1804,6 +1825,7 @@ def initialise_wallets(
|
|||
Coins.DOGE,
|
||||
Coins.DCR,
|
||||
Coins.DASH,
|
||||
Coins.NMC,
|
||||
)
|
||||
# Always start Particl, it must be running to initialise a wallet in addcoin mode
|
||||
# Particl must be loaded first as subsequent coins are initialised from the Particl mnemonic
|
||||
|
@ -1909,7 +1931,7 @@ def initialise_wallets(
|
|||
f'Creating wallet "{wallet_name}" for {getCoinName(c)}.'
|
||||
)
|
||||
|
||||
if c in (Coins.BTC, Coins.LTC, Coins.DOGE, Coins.DASH):
|
||||
if c in (Coins.BTC, Coins.LTC, Coins.NMC, Coins.DOGE, Coins.DASH):
|
||||
# wallet_name, disable_private_keys, blank, passphrase, avoid_reuse, descriptors
|
||||
|
||||
use_descriptors = coin_settings.get("use_descriptors", False)
|
||||
|
@ -1926,11 +1948,15 @@ def initialise_wallets(
|
|||
],
|
||||
)
|
||||
if use_descriptors:
|
||||
watch_wallet_name = coin_settings["watch_wallet_name"]
|
||||
logger.info(
|
||||
f'Creating wallet "{watch_wallet_name}" for {getCoinName(c)}.'
|
||||
)
|
||||
swap_client.callcoinrpc(
|
||||
c,
|
||||
"createwallet",
|
||||
[
|
||||
coin_settings["watch_wallet_name"],
|
||||
watch_wallet_name,
|
||||
True,
|
||||
True,
|
||||
"",
|
||||
|
@ -2073,7 +2099,10 @@ def check_btc_fastsync_data(base_dir, sync_filename):
|
|||
importPubkey(gpg, pubkey_filename, pubkeyurls)
|
||||
with open(asc_file_path, "rb") as fp:
|
||||
verified = gpg.verify_file(fp)
|
||||
if isValidSignature(verified) and verified.key_id in expected_key_ids["tecnovert"]:
|
||||
if (
|
||||
isValidSignature(verified)
|
||||
and verified.fingerprint in expected_key_ids["tecnovert"]
|
||||
):
|
||||
ensureValidSignatureBy(verified, "tecnovert")
|
||||
else:
|
||||
pubkey_filename = "nicolasdorier.asc"
|
||||
|
@ -2379,22 +2408,6 @@ def main():
|
|||
"core_version_no": getKnownVersion("bitcoin"),
|
||||
"core_version_group": 28,
|
||||
},
|
||||
"bitcoincash": {
|
||||
"connection_type": "rpc",
|
||||
"manage_daemon": shouldManageDaemon("BCH"),
|
||||
"rpchost": BCH_RPC_HOST,
|
||||
"rpcport": BCH_RPC_PORT + port_offset,
|
||||
"onionport": BCH_ONION_PORT + port_offset,
|
||||
"datadir": os.getenv("BCH_DATA_DIR", os.path.join(data_dir, "bitcoincash")),
|
||||
"bindir": os.path.join(bin_dir, "bitcoincash"),
|
||||
"port": BCH_PORT + port_offset,
|
||||
"config_filename": "bitcoin.conf",
|
||||
"use_segwit": False,
|
||||
"blocks_confirmed": 1,
|
||||
"conf_target": 2,
|
||||
"core_version_no": getKnownVersion("bitcoincash"),
|
||||
"core_version_group": 22,
|
||||
},
|
||||
"litecoin": {
|
||||
"connection_type": "rpc",
|
||||
"manage_daemon": shouldManageDaemon("LTC"),
|
||||
|
@ -2410,22 +2423,6 @@ def main():
|
|||
"core_version_group": 20,
|
||||
"min_relay_fee": 0.00001,
|
||||
},
|
||||
"dogecoin": {
|
||||
"connection_type": "rpc",
|
||||
"manage_daemon": shouldManageDaemon("DOGE"),
|
||||
"rpchost": DOGE_RPC_HOST,
|
||||
"rpcport": DOGE_RPC_PORT + port_offset,
|
||||
"onionport": DOGE_ONION_PORT + port_offset,
|
||||
"datadir": os.getenv("DOGE_DATA_DIR", os.path.join(data_dir, "dogecoin")),
|
||||
"bindir": os.path.join(bin_dir, "dogecoin"),
|
||||
"use_segwit": False,
|
||||
"use_csv": False,
|
||||
"blocks_confirmed": 2,
|
||||
"conf_target": 2,
|
||||
"core_version_no": getKnownVersion("dogecoin"),
|
||||
"core_version_group": 23,
|
||||
"min_relay_fee": 0.01, # RECOMMENDED_MIN_TX_FEE
|
||||
},
|
||||
"decred": {
|
||||
"connection_type": "rpc",
|
||||
"manage_daemon": shouldManageDaemon("DCR"),
|
||||
|
@ -2453,14 +2450,16 @@ def main():
|
|||
"manage_daemon": shouldManageDaemon("NMC"),
|
||||
"rpchost": NMC_RPC_HOST,
|
||||
"rpcport": NMC_RPC_PORT + port_offset,
|
||||
"onionport": NMC_ONION_PORT + port_offset,
|
||||
"datadir": os.getenv("NMC_DATA_DIR", os.path.join(data_dir, "namecoin")),
|
||||
"bindir": os.path.join(bin_dir, "namecoin"),
|
||||
"use_segwit": False,
|
||||
"use_csv": False,
|
||||
"port": NMC_PORT + port_offset,
|
||||
"use_segwit": True,
|
||||
"use_csv": True,
|
||||
"blocks_confirmed": 1,
|
||||
"conf_target": 2,
|
||||
"core_version_no": getKnownVersion("namecoin"),
|
||||
"core_version_group": 18,
|
||||
"core_version_group": 28,
|
||||
"chain_lookups": "local",
|
||||
},
|
||||
"monero": {
|
||||
|
@ -2486,6 +2485,28 @@ def main():
|
|||
"core_version_no": getKnownVersion("monero"),
|
||||
"core_type_group": "xmr",
|
||||
},
|
||||
"wownero": {
|
||||
"connection_type": "rpc",
|
||||
"manage_daemon": shouldManageDaemon("WOW"),
|
||||
"manage_wallet_daemon": shouldManageDaemon("WOW_WALLET"),
|
||||
"rpcport": WOW_RPC_PORT + port_offset,
|
||||
"zmqport": WOW_ZMQ_PORT + port_offset,
|
||||
"walletrpcport": WOW_WALLET_RPC_PORT + port_offset,
|
||||
"rpchost": WOW_RPC_HOST,
|
||||
"trusted_daemon": extra_opts.get("trust_remote_node", "auto"),
|
||||
"walletrpchost": WOW_WALLET_RPC_HOST,
|
||||
"walletrpcuser": WOW_WALLET_RPC_USER,
|
||||
"walletrpcpassword": WOW_WALLET_RPC_PWD,
|
||||
"datadir": os.getenv("WOW_DATA_DIR", os.path.join(data_dir, "wownero")),
|
||||
"bindir": os.path.join(bin_dir, "wownero"),
|
||||
"restore_height": wow_restore_height,
|
||||
"blocks_confirmed": 2,
|
||||
"rpctimeout": 60,
|
||||
"walletrpctimeout": 120,
|
||||
"walletrpctimeoutlong": 300,
|
||||
"core_version_no": getKnownVersion("wownero"),
|
||||
"core_type_group": "xmr",
|
||||
},
|
||||
"pivx": {
|
||||
"connection_type": "rpc",
|
||||
"manage_daemon": shouldManageDaemon("PIVX"),
|
||||
|
@ -2549,27 +2570,37 @@ def main():
|
|||
"chain_lookups": "local",
|
||||
"startup_tries": 40,
|
||||
},
|
||||
"wownero": {
|
||||
"bitcoincash": {
|
||||
"connection_type": "rpc",
|
||||
"manage_daemon": shouldManageDaemon("WOW"),
|
||||
"manage_wallet_daemon": shouldManageDaemon("WOW_WALLET"),
|
||||
"rpcport": WOW_RPC_PORT + port_offset,
|
||||
"zmqport": WOW_ZMQ_PORT + port_offset,
|
||||
"walletrpcport": WOW_WALLET_RPC_PORT + port_offset,
|
||||
"rpchost": WOW_RPC_HOST,
|
||||
"trusted_daemon": extra_opts.get("trust_remote_node", "auto"),
|
||||
"walletrpchost": WOW_WALLET_RPC_HOST,
|
||||
"walletrpcuser": WOW_WALLET_RPC_USER,
|
||||
"walletrpcpassword": WOW_WALLET_RPC_PWD,
|
||||
"datadir": os.getenv("WOW_DATA_DIR", os.path.join(data_dir, "wownero")),
|
||||
"bindir": os.path.join(bin_dir, "wownero"),
|
||||
"restore_height": wow_restore_height,
|
||||
"manage_daemon": shouldManageDaemon("BCH"),
|
||||
"rpchost": BCH_RPC_HOST,
|
||||
"rpcport": BCH_RPC_PORT + port_offset,
|
||||
"onionport": BCH_ONION_PORT + port_offset,
|
||||
"datadir": os.getenv("BCH_DATA_DIR", os.path.join(data_dir, "bitcoincash")),
|
||||
"bindir": os.path.join(bin_dir, "bitcoincash"),
|
||||
"port": BCH_PORT + port_offset,
|
||||
"config_filename": "bitcoin.conf",
|
||||
"use_segwit": False,
|
||||
"blocks_confirmed": 1,
|
||||
"conf_target": 2,
|
||||
"core_version_no": getKnownVersion("bitcoincash"),
|
||||
"core_version_group": 22,
|
||||
},
|
||||
"dogecoin": {
|
||||
"connection_type": "rpc",
|
||||
"manage_daemon": shouldManageDaemon("DOGE"),
|
||||
"rpchost": DOGE_RPC_HOST,
|
||||
"rpcport": DOGE_RPC_PORT + port_offset,
|
||||
"onionport": DOGE_ONION_PORT + port_offset,
|
||||
"datadir": os.getenv("DOGE_DATA_DIR", os.path.join(data_dir, "dogecoin")),
|
||||
"bindir": os.path.join(bin_dir, "dogecoin"),
|
||||
"use_segwit": False,
|
||||
"use_csv": False,
|
||||
"blocks_confirmed": 2,
|
||||
"rpctimeout": 60,
|
||||
"walletrpctimeout": 120,
|
||||
"walletrpctimeoutlong": 300,
|
||||
"core_version_no": getKnownVersion("wownero"),
|
||||
"core_type_group": "xmr",
|
||||
"conf_target": 2,
|
||||
"core_version_no": getKnownVersion("dogecoin"),
|
||||
"core_version_group": 23,
|
||||
"min_relay_fee": 0.01, # RECOMMENDED_MIN_TX_FEE
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -2593,9 +2624,8 @@ def main():
|
|||
coin_settings["wallet_name"] = set_name
|
||||
|
||||
ticker: str = coin_params["ticker"]
|
||||
if toBool(os.getenv(ticker + "_USE_DESCRIPTORS", False)):
|
||||
|
||||
if coin_id not in (Coins.BTC,):
|
||||
if getDescriptorWalletOption(coin_params):
|
||||
if coin_id not in (Coins.BTC, Coins.NMC):
|
||||
raise ValueError(f"Descriptor wallet unavailable for {coin_name}")
|
||||
|
||||
coin_settings["use_descriptors"] = True
|
||||
|
|
|
@ -265,7 +265,11 @@ def getCoreBinArgs(coin_id: int, coin_settings, prepare=False, use_tor_proxy=Fal
|
|||
# As BCH may use port 8334, disable it here.
|
||||
# When tor is enabled a bind option for the onionport will be added to bitcoin.conf.
|
||||
# https://github.com/bitcoin/bitcoin/blob/master/doc/release-notes/release-notes-28.0.md?plain=1#L84
|
||||
if prepare is False and use_tor_proxy is False and coin_id == Coins.BTC:
|
||||
if (
|
||||
prepare is False
|
||||
and use_tor_proxy is False
|
||||
and coin_id in (Coins.BTC, Coins.NMC)
|
||||
):
|
||||
port: int = coin_settings.get("port", 8333)
|
||||
extra_args.append(f"--bind=0.0.0.0:{port}")
|
||||
return extra_args
|
||||
|
|
|
@ -58,6 +58,8 @@ chainparams = {
|
|||
"bip44": 44,
|
||||
"min_amount": 100000,
|
||||
"max_amount": 10000000 * COIN,
|
||||
"ext_public_key_prefix": 0x696E82D1,
|
||||
"ext_secret_key_prefix": 0x8F1DAEB8,
|
||||
},
|
||||
"testnet": {
|
||||
"rpcport": 51935,
|
||||
|
@ -69,6 +71,8 @@ chainparams = {
|
|||
"bip44": 1,
|
||||
"min_amount": 100000,
|
||||
"max_amount": 10000000 * COIN,
|
||||
"ext_public_key_prefix": 0xE1427800,
|
||||
"ext_secret_key_prefix": 0x04889478,
|
||||
},
|
||||
"regtest": {
|
||||
"rpcport": 51936,
|
||||
|
@ -80,6 +84,8 @@ chainparams = {
|
|||
"bip44": 1,
|
||||
"min_amount": 100000,
|
||||
"max_amount": 10000000 * COIN,
|
||||
"ext_public_key_prefix": 0xE1427800,
|
||||
"ext_secret_key_prefix": 0x04889478,
|
||||
},
|
||||
},
|
||||
Coins.BTC: {
|
||||
|
@ -251,29 +257,38 @@ chainparams = {
|
|||
"rpcport": 8336,
|
||||
"pubkey_address": 52,
|
||||
"script_address": 13,
|
||||
"key_prefix": 180,
|
||||
"hrp": "nc",
|
||||
"bip44": 7,
|
||||
"min_amount": 100000,
|
||||
"max_amount": 10000000 * COIN,
|
||||
"ext_public_key_prefix": 0x0488B21E, # base58Prefixes[EXT_PUBLIC_KEY]
|
||||
"ext_secret_key_prefix": 0x0488ADE4,
|
||||
},
|
||||
"testnet": {
|
||||
"rpcport": 18336,
|
||||
"pubkey_address": 111,
|
||||
"script_address": 196,
|
||||
"key_prefix": 239,
|
||||
"hrp": "tn",
|
||||
"bip44": 1,
|
||||
"min_amount": 100000,
|
||||
"max_amount": 10000000 * COIN,
|
||||
"name": "testnet3",
|
||||
"ext_public_key_prefix": 0x043587CF,
|
||||
"ext_secret_key_prefix": 0x04358394,
|
||||
},
|
||||
"regtest": {
|
||||
"rpcport": 18443,
|
||||
"pubkey_address": 111,
|
||||
"script_address": 196,
|
||||
"key_prefix": 239,
|
||||
"hrp": "ncrt",
|
||||
"bip44": 1,
|
||||
"min_amount": 100000,
|
||||
"max_amount": 10000000 * COIN,
|
||||
"ext_public_key_prefix": 0x043587CF,
|
||||
"ext_secret_key_prefix": 0x04358394,
|
||||
},
|
||||
},
|
||||
Coins.XMR: {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2019-2024 The Basicswap developers
|
||||
# Copyright (c) 2019-2025 The Basicswap developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
|
@ -40,13 +40,6 @@ DOGECOIND = os.getenv("DOGECOIND", "dogecoind" + bin_suffix)
|
|||
DOGECOIN_CLI = os.getenv("DOGECOIN_CLI", "dogecoin-cli" + bin_suffix)
|
||||
DOGECOIN_TX = os.getenv("DOGECOIN_TX", "dogecoin-tx" + bin_suffix)
|
||||
|
||||
NAMECOIN_BINDIR = os.path.expanduser(
|
||||
os.getenv("NAMECOIN_BINDIR", os.path.join(DEFAULT_TEST_BINDIR, "namecoin"))
|
||||
)
|
||||
NAMECOIND = os.getenv("NAMECOIND", "namecoind" + bin_suffix)
|
||||
NAMECOIN_CLI = os.getenv("NAMECOIN_CLI", "namecoin-cli" + bin_suffix)
|
||||
NAMECOIN_TX = os.getenv("NAMECOIN_TX", "namecoin-tx" + bin_suffix)
|
||||
|
||||
XMR_BINDIR = os.path.expanduser(
|
||||
os.getenv("XMR_BINDIR", os.path.join(DEFAULT_TEST_BINDIR, "monero"))
|
||||
)
|
||||
|
|
|
@ -1862,20 +1862,70 @@ class BTCInterface(Secp256k1Interface):
|
|||
"Could not find address with enough funds for proof",
|
||||
)
|
||||
|
||||
self._log.debug("sign_for_addr %s", sign_for_addr)
|
||||
self._log.debug(f"sign_for_addr {sign_for_addr}")
|
||||
|
||||
funds_addr: str = sign_for_addr
|
||||
if (
|
||||
self.using_segwit()
|
||||
): # TODO: Use isSegwitAddress when scantxoutset can use combo
|
||||
# 'Address does not refer to key' for non p2pkh
|
||||
pkh = self.decodeAddress(sign_for_addr)
|
||||
sign_for_addr = self.pkh_to_address(pkh)
|
||||
self._log.debug("sign_for_addr converted %s", sign_for_addr)
|
||||
self._log.debug(f"sign_for_addr converted {sign_for_addr}")
|
||||
|
||||
signature = self.rpc_wallet(
|
||||
"signmessage",
|
||||
[sign_for_addr, sign_for_addr + "_swap_proof_" + extra_commit_bytes.hex()],
|
||||
)
|
||||
if self._use_descriptors:
|
||||
# https://github.com/bitcoin/bitcoin/issues/10542
|
||||
# https://github.com/bitcoin/bitcoin/issues/26046
|
||||
priv_keys = self.rpc_wallet(
|
||||
"listdescriptors",
|
||||
[
|
||||
True,
|
||||
],
|
||||
)
|
||||
addr_info = self.rpc_wallet(
|
||||
"getaddressinfo",
|
||||
[
|
||||
funds_addr,
|
||||
],
|
||||
)
|
||||
hdkeypath = addr_info["hdkeypath"]
|
||||
|
||||
sign_for_address_key = None
|
||||
for descriptor in priv_keys["descriptors"]:
|
||||
if descriptor["active"] is False or descriptor["internal"] is True:
|
||||
continue
|
||||
desc = descriptor["desc"]
|
||||
assert desc.startswith("wpkh(")
|
||||
ext_key = desc[5:].split(")")[0].split("/", 1)[0]
|
||||
ext_key_data = decodeAddress(ext_key)[4:]
|
||||
ci_part = self._sc.ci(Coins.PART)
|
||||
ext_key_data_part = ci_part.encode_secret_extkey(ext_key_data)
|
||||
rv = ci_part.rpc_wallet(
|
||||
"extkey", ["info", ext_key_data_part, hdkeypath]
|
||||
)
|
||||
extkey_derived = rv["key_info"]["result"]
|
||||
ext_key_data = decodeAddress(extkey_derived)[4:]
|
||||
ek = ExtKeyPair()
|
||||
ek.decode(ext_key_data)
|
||||
sign_for_address_key = self.encodeKey(ek._key)
|
||||
break
|
||||
assert sign_for_address_key is not None
|
||||
signature = self.rpc(
|
||||
"signmessagewithprivkey",
|
||||
[
|
||||
sign_for_address_key,
|
||||
sign_for_addr + "_swap_proof_" + extra_commit_bytes.hex(),
|
||||
],
|
||||
)
|
||||
del priv_keys
|
||||
else:
|
||||
signature = self.rpc_wallet(
|
||||
"signmessage",
|
||||
[
|
||||
sign_for_addr,
|
||||
sign_for_addr + "_swap_proof_" + extra_commit_bytes.hex(),
|
||||
],
|
||||
)
|
||||
|
||||
prove_utxos = [] # TODO: Send specific utxos
|
||||
return (sign_for_addr, signature, prove_utxos)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2020-2022 tecnovert
|
||||
# Copyright (c) 2025 The Basicswap developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
|
@ -13,39 +14,3 @@ class NMCInterface(BTCInterface):
|
|||
@staticmethod
|
||||
def coin_type():
|
||||
return Coins.NMC
|
||||
|
||||
def getLockTxHeight(
|
||||
self,
|
||||
txid,
|
||||
dest_address,
|
||||
bid_amount,
|
||||
rescan_from,
|
||||
find_index: bool = False,
|
||||
vout: int = -1,
|
||||
):
|
||||
self._log.debug("[rm] scantxoutset start") # scantxoutset is slow
|
||||
ro = self.rpc(
|
||||
"scantxoutset", ["start", ["addr({})".format(dest_address)]]
|
||||
) # TODO: Use combo(address) where possible
|
||||
self._log.debug("[rm] scantxoutset end")
|
||||
return_txid = True if txid is None else False
|
||||
for o in ro["unspents"]:
|
||||
if txid and o["txid"] != txid.hex():
|
||||
continue
|
||||
# Verify amount
|
||||
if self.make_int(o["amount"]) != int(bid_amount):
|
||||
self._log.warning(
|
||||
"Found output to lock tx address of incorrect value: %s, %s",
|
||||
str(o["amount"]),
|
||||
o["txid"],
|
||||
)
|
||||
continue
|
||||
|
||||
rv = {"depth": 0, "height": o["height"]}
|
||||
if o["height"] > 0:
|
||||
rv["depth"] = ro["height"] - o["height"]
|
||||
if find_index:
|
||||
rv["index"] = o["vout"]
|
||||
if return_txid:
|
||||
rv["txid"] = o["txid"]
|
||||
return rv
|
||||
|
|
25
basicswap/pgp/keys/bitcoincash_Calin_Culianu.pgp
Normal file
25
basicswap/pgp/keys/bitcoincash_Calin_Culianu.pgp
Normal file
|
@ -0,0 +1,25 @@
|
|||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQMuBFmZ6L4RCACuqDDCIe2bzKznyKVN1aInzRQnSxdGTXuw0mcDz5HYudAhBjR8
|
||||
gY6sxCRPNxvZCJVDZDpCygXMhWZlJtWLR8KMTCXxC4HLXXOY4RxQ5KGnYWxEAcKY
|
||||
deq1ymmuOuMUp7ltRTSyWcBKbR9xTd2vW/+0W7GQIOxUW/aiT1V0x3cky+6kqaec
|
||||
BorP3+uxJcx0Q8WdlS/6N4x3pBv/lfsdrZSaDD8fU/29pQGMDUEnupKoWJVVei6r
|
||||
G+vxLHEtIFYYO8VWjZntymw3dl+aogrjyuxqWzl8mfPi9M/DgiRb4pJnH2yOGDI6
|
||||
Lvg+oo9E79Vwi98UjYSicsB1dtcptKiA96UXAQD/hDB+dil7/SX/SDTlaw/+uTdd
|
||||
Xg0No63dbN++iY4k3Qf/Xk1ZzbuDviLhe+zEhlJOw6TaMlxfwwQOtxEJXILS5uIL
|
||||
jYlGcDbBtJh3p4qUoUduDOgjumJ9m47XqIq81rQ0pqzzGMbK1Y82NQjX5Sn8yTm9
|
||||
p1hmOZ/uX9vCrUSbYBjxJXyQ1OXlerlLRLfBf5WQ0+LO+0cmgtCyX0zV4oGK7vph
|
||||
XEm7lar7AezOOXaSrWAB+CTPUdJF1E7lcJiUuMVcqMx8pphrH+rfcsqPtN6tkyUD
|
||||
TmPDpc5ViqFFelEEQnKSlmAY+3iCNZ3y/VdPPhuJ2lAsL3tm9MMh2JGV378LG45a
|
||||
6SOkQrC977Qq1dhgJA+PGJxQvL2RJWsYlJwp79+Npgf9EfFaJVNzbdjGVq1XmNie
|
||||
MZYqHRfABkyK0ooDxSyzJrq4vvuhWKInS4JhpKSabgNSsNiiaoDR+YYMHb0H8GRR
|
||||
Za6JCmfU8w97R41UTI32N7dhul4xCDs5OV6maOIoNts20oigNGb7TKH9b5N7sDJB
|
||||
zh3Of/fHCChO9Y2chbzU0bERfcn+evrWBf/9XdQGQ3ggoLbOtGpcUQuB/7ofTcBZ
|
||||
awL6K4VJ2Qlb8DPlRgju6uU9AR/KTYeAlVFC8FX7R0FGgPRcJ3GNkNHGqrbuQ72q
|
||||
AOhYOPx9nRrU5u+E2J325vOabLnLbOazze3j6LFPSFV4vfmTO9exYlwhz3g+lFAd
|
||||
CrQ2Q2FsaW4gQ3VsaWFudSAoTmlsYWNUaGVHcmltKSA8Y2FsaW4uY3VsaWFudUBn
|
||||
bWFpbC5jb20+iHoEExEIACIFAlmZ6L4CGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4B
|
||||
AheAAAoJECGBClQgMcAsU5cBAO/ngONpHsxny2uTV4ge2f+5V2ajTjcIfN2jUZtg
|
||||
31jJAQCl1NcrwcIu98+aM2IyjB1UFXkoaMANpr8L9jBopivRGQ==
|
||||
=cf8I
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
|
@ -1,14 +0,0 @@
|
|||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mDMEXPNfCBYJKwYBBAHaRw8BAQdAWGFiEJYnlV2TDTesLIO/eoQ3IPduzcG97GpA
|
||||
6K+Gj+K0K0BKZXJlbXlSYW5kIG9uIEdpdEh1YiA8amVyZW15QG5hbWVjb2luLm9y
|
||||
Zz6IlgQTFggAPhYhBJza8EpykDv+wJWdvi2+M54p9ilMBQJc88q7AhsDBQkB4TOA
|
||||
BQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEC2+M54p9ilMMUoA/1oZn8AtwQ7D
|
||||
wXgNKq++zqHaiEcHGgsyFeDRbQARsYRVAQDxa36p181id1YuMjeV1KhC5vaDS4nY
|
||||
GB4FHPsQ4bbqDLRESmVyZW15IFJhbmQgKE5hbWVjb2luIENvcmUgR2l0aWFuIFNp
|
||||
Z25pbmcgS2V5KSA8amVyZW15QG5hbWVjb2luLm9yZz6ImQQTFggAQQIbAwUJAeEz
|
||||
gAULCQgHAgYVCgkICwIEFgIDAQIeAQIXgBYhBJza8EpykDv+wJWdvi2+M54p9ilM
|
||||
BQJc9WDrAhkBAAoJEC2+M54p9ilMz3IA/3mCKeFYcEJFlwP43mdIMGOV2zt/R4Fn
|
||||
z/rBJpv5hFoHAQDXAY8+mbY/9N+5Rn8Iy51tXEaTq3khdruuFFdty+bXAg==
|
||||
=EpnJ
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
52
basicswap/pgp/keys/namecoin_RoseTuring.pgp
Normal file
52
basicswap/pgp/keys/namecoin_RoseTuring.pgp
Normal file
|
@ -0,0 +1,52 @@
|
|||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
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
|
||||
=atlH
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
|
@ -1,78 +1,29 @@
|
|||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQENBFlLyDYBCADqup3EHjFCMELf4I0smf4hDl48qDn/Hue08JLmSToMc7z9ylLk
|
||||
6Uzx6S1m7RiDO63A7yW4qyRkb54VNj+6rUSPNt2uVy1vT8OEQJAZLf2c4qpaKHAQ
|
||||
QV3utu8pYxYOJfLHh4zNEGXrbSrjDv/FTPuri+SkIABhjf70ZSocm4l49rtBanK5
|
||||
AIAp8DoXWcUdbwmAfl6qrLfzrDu75kq+bspd8p4CVy4fzdOtr6LvXW38z1t3XtLP
|
||||
+EGVMAzZQWr2WbN762rK7skH+ZfhaMjAwr8gPYymYnFGLdS1nBmhksnulQNGQOro
|
||||
WojsvQKgBJoGUnp/OrVpi3gn7UNfDo99CxMRABEBAAG0IHRlY25vdmVydCA8dGVj
|
||||
bm92ZXJ0QHBhcnRpY2wuaW8+iQFUBBMBCAA+FiEEOQGTZk5wi3vnahADcJ5tyVzr
|
||||
Ac8FAllLyDYCGwMFCQPCZwAFCwkIBwIGFQgJCgsCBBYCAwECHgECF4AACgkQcJ5t
|
||||
yVzrAc+0LAf/SvBJFJGq1yT9pdLT+7lv7BrshfSYQBLNqPmPrxRuxzH3q/EaEk6D
|
||||
oQh/Jk4vmSXR1y+bsKtS55ekGsPZZWlUFMbXDuU0II3YkWewHXTnqxLtqzcWODoK
|
||||
6vPonjiVuhYC57d4TWw5ebzHy8wICunyVeaL/cvYQM1TfaI2fN5v0Ep+XiRpH/15
|
||||
HQzRaynKq58w7gH79mPIRA2WFz4eMIMWS3rSa+cSoJ0MhpimgnKUDlh2DebVP1eH
|
||||
keSW1JlPZHhca/XB93ghFlbO6wOrbg+gsKtB45OkpsoOzUMFIKVJLBAjK751dTcc
|
||||
Pb4xTzABaBXxk+IUxgGB1h+g3i6wzksfgLkBDQRZS8g2AQgAw7Db3G5J21jsty9S
|
||||
pMmqp93dgZFm8E4VTcsL4KVvZybhwHngNHnhG8G/DWQ53o07/BKorfRBmFD3x2Eq
|
||||
RqfOn4ytmZVw/sOjbZPi4m/tF8z+O9qR8I0CzedYip21rwz2j4UgnpDQ+BnOpyXB
|
||||
H0gDBlPFq8ih9kkm413QRTTKnkRM/U8SfyFU8vIFdH7T0Ae07m0LxePDaTyxLPg3
|
||||
x1+RvEjVkruc3/9Z4kzexoUv654wirRdxPX8GsWI1WNDQrj4GqmpF/e0WDM97+Lk
|
||||
DGzbcXy7TGMIHQx8QFlFwdSZv9x70574as9Od4jOWTk90sopSMr8t6H6wTdn+2MD
|
||||
qsZKUwARAQABiQE8BBgBCAAmFiEEOQGTZk5wi3vnahADcJ5tyVzrAc8FAllLyDYC
|
||||
GwwFCQPCZwAACgkQcJ5tyVzrAc/QFgf8CQydF/VqJtujQC/rjB1YYNQcljzoeQWA
|
||||
2F2O5cF5skTNYy+xas3PTgxfOpn5iTpixpkB+I7X8LwoPmRjZvg2MFirDVXUypcx
|
||||
HwMbQqYCuAaK1EhtVUVYbFGjM67nClmBApLdenbqEP/BhyR9kgDCBt7ZvSLe5N/6
|
||||
MKYJF1FlCgGc5OJPJrMIl0slU5QtzRy5J+l75WflkgxFUKJPotJ5Z+yduxOff//e
|
||||
qSEXqlkaebWT0ZFiAqHhExJCRJ5HBqQEdW4JHrB7j3bNh8Qdf8epiYtcXXSsE9+K
|
||||
XEP7UJRk5bFFKdn0wMONgmQLMjjspU5byMQDJ0hFNMmmrbKX2AXqRpkCDQRZS8mC
|
||||
ARAA1t6CZ1TAwveIPuzgdfyAVGDXrwqiSDgLQtHnhUuYNFxr76kS8djS1Kp+bXvk
|
||||
e3XqBhJZGRSSy8RVMBJ4ahgkR+dCKLuWmp1M74COX1QGyt5NH6fb3CygkdH0FSIn
|
||||
XC8qjKZC2aPAUhN/gVsRaf69jh74dnWLSQvgWVcG5ZA0t3KsCr1GcSKHLw7OO1qN
|
||||
7c2XxLKlGr224hsfg5tHwle01R3VS1O6t22bB0kYsk1GdhAAKaAJk4q/XLFcb9iD
|
||||
PMn+vx8Fouvy6e3YEhtfqgWdZVDz02PnRSz2crf5Lpfr7jo+hi2WlLNw+une02jw
|
||||
hylgDpz/UR6YnP4lzg11V6NShyX2tMfH1uyPsu/xm/ucf5uDtAc9kwYr3a0gLhaV
|
||||
5D6sGsJcOAj4CPX3PNNYPN/mRcw9oyeqsZBIH55Zn/sxjZ+bQuDeYzUU0Phsh6Nc
|
||||
OPNuEl3EjefdMIM/IKBiQt0DycW4n7zgPBs0CFc6cR3JKHzlcqiBKqkp5D9sZ+Jh
|
||||
C6g+x3BZ6KI2QahWxdnDfqFkPp4izfr+Kq1J3KUCPUlVpcqeukvtUwYQUI9kLl/t
|
||||
wfituxIg24TVexF+sRGxrJwdaaDHNmjIs+r3sm1txp6DPtqaa/CqP9diI+5fmQOO
|
||||
Lej1lH0EGzUm1JP9GIXfUCfFUFXJPk2kuoLWq021EZUnZh8AEQEAAbQpdGVjbm92
|
||||
ZXJ0IChnaXRpYW4pIDx0ZWNub3ZlcnRAcGFydGljbC5pbz6JAlQEEwEIAD4WIQSO
|
||||
UX3BLsHMN/ZCOooT8TZRyc8NawUCWUvJggIbAwUJEswDAAULCQgHAgYVCAkKCwIE
|
||||
FgIDAQIeAQIXgAAKCRAT8TZRyc8Na7XWD/9tokV/DtkPvjGsjxzceVxwJTJPZn4u
|
||||
RQdaicLIbZYXWuz/VP4Tk4ttu8B/jM4eXQY3uLdg5KB88Zc/1q+HEEFCTDmHdDhG
|
||||
WOpKQEJL7cmKGyG+s5UUCtZKAHzTMXsJn2WRk5a9eiFFQqLxkhb2foXWEQxI7h6l
|
||||
46cAX68RQMvxwp32NdKkkZCXOcNcqY9SJM5Wp0vsXkSUg70U0AwBK8798SnDBowg
|
||||
h2mgj/rcgGlYgWlDpb5mXVsINIMEArjy6iIdHHw23INKrnIkSKZ8qcyDZn8J4GQs
|
||||
F3SGHwM5gszB8NSd4joqn6itBHKRzLC+vPVckEj4LKBB7XDhh2I0S6TDxr0RR7SA
|
||||
q5whxDStyHMBVgxl1vot84DpQO4OPMmFlr0rqfrfCOmE/hXnhZcUjnY9RnXjANDu
|
||||
4F2e85y1XbqJC9hH+HWY3PtzcAZRaL+dr8AmcEDABrDK4sBAwdqw2Qe2DrwMZVAf
|
||||
5Gr7cf6BPH1e5mXLsGINNpauG6MxfcZYYzhWkYresV5y1YtE7iO+nLs+u5wfVZFn
|
||||
M0iyMwsozchaVm8dQTMU2H3oWV9/mDWo18Buh3RKfQgGCtLuOhrs/z7Yeu22zVWM
|
||||
j/3LjiK7/4akOsaOJjgTAw8XAhAF8d68MX28TTPL5cKzHKSE67TTja+NW3MVCHzB
|
||||
A3nz5ucJ13qfFrkCDQRZS8mCARAA7QMvR0fFA1FZKzcS6/W5Jcm0g6FQ1xHaMeEh
|
||||
LECOQpM3wSOL1A8trbpC2VgMLjRFq+h3YQRlF8Y4oIaIz2UzziqK6mGZxhtEN6y3
|
||||
IIXrVC5CTpcDXxlvJyHeHQONvMnEbmnbHfZAtxJq2wFOr7BWiLVzfioyNSND/JOP
|
||||
VlgezL6YRAocQbHU7mQKY7gCqU4jDZIxru01e2hoIHSbAFXjmEcFBFoErWXAMf5w
|
||||
HaK7dGGMpJXgNCK2weatNCBxD/krv1gA7nheT665K7HUQxu/NhUIk8XnOPD5iDoJ
|
||||
zeQXHY3SM8jrhhabRubm27c/Oads9lgk9EGZhxLhIMQ9jUu7TsX1sPZpfnoE/JAq
|
||||
ofY3WwimOXYb+p0jetg4FQaqul6FpgesSI4Nl5nHHB8/4CWUv2oV2YjUJlBpazyc
|
||||
ullt8a7GdwzQMbiw23Jgz1frrMuq/zQc4wLGUFchhnYMrva+6t0ewjxD7bCL/7N7
|
||||
3UDdNpVi+ZcBVQPVididC4iRcCLDqmr+WtTfVKw58Rnb7Qt9Z+2MqVZa1/numTG1
|
||||
DastjRg6KGkN6eYaxKcXHf7t/lYZ5ejGFVUh+wtwlb1tTpOvWKq130tuO/aDWTa2
|
||||
jViwy2UUpbyg5UbBvd0PHTJ+8TTdxEoC5wQCYHZ5Ueg9wwLhs0VQ44GI7vnXJZ8b
|
||||
aXUe/mEAEQEAAYkCPAQYAQgAJhYhBI5RfcEuwcw39kI6ihPxNlHJzw1rBQJZS8mC
|
||||
AhsMBQkSzAMAAAoJEBPxNlHJzw1r+3YQAM5648S/oQLnK5WO0/w3gIUI5g7BrdJO
|
||||
kRINe8SNYs6PvCFjKij/3p9YMxrc/TojTQfhxew7bNxkhDU7sudxIr6TcKW5SK9f
|
||||
g9zz2Ib5heR+orjPSX9hgSLX66t4DvJfdph+O1O3l83g0bsDUPCivTSnQ5XtdiVK
|
||||
ytOoM26/GaQHwzKbk1Qzn1nrZeLaeDAsJ30GdmteNRMof1G2H9kg/33xbcyRCMaT
|
||||
xjKS0ssa8RUmxuYsR+fjc7t5FvXwnfoXapkqUWcddFCCgAiTc0NZjzcDSXVB/++2
|
||||
KxLZ0Q86kuJwdb7KEq0SwPQAM6ikmIaoke9fJAZzhyyWX7AeSQx1ime31Xrjh0CC
|
||||
MHW+PdQMpLSNTAHEZDuybGKaShVMiHASXs7XsnJr6lOObMYzSGr0+B5fQWU7aHlM
|
||||
u+4YNHUwQldx/EqkL/DjIpocVC5ozaW+dV1zSMLBHdk24soWI+gLrL3FG0NMyNZ+
|
||||
O95X/bB/X+dqOBYpitR3xpYZes4Jl4Kechi60+mdDktFKfKfiRxyJlg2LNd7/OLB
|
||||
hpxg2zsXlHhqhSJAo9IGih2rOgcMwtCXKmHCGG5KGsNF8x3H9bPOwynAUMqUJ2cR
|
||||
7BCjzmUxUnsLcJnokUnHMbECZ+pee9YcaRNrlbVAIvED3ZHEhFJxIMaArxSLmRwE
|
||||
XHovfCfpcB/C
|
||||
=0Wkp
|
||||
mQINBFlLyYIBEADW3oJnVMDC94g+7OB1/IBUYNevCqJIOAtC0eeFS5g0XGvvqRLx
|
||||
2NLUqn5te+R7deoGElkZFJLLxFUwEnhqGCRH50Iou5aanUzvgI5fVAbK3k0fp9vc
|
||||
LKCR0fQVIidcLyqMpkLZo8BSE3+BWxFp/r2OHvh2dYtJC+BZVwblkDS3cqwKvUZx
|
||||
IocvDs47Wo3tzZfEsqUavbbiGx+Dm0fCV7TVHdVLU7q3bZsHSRiyTUZ2EAApoAmT
|
||||
ir9csVxv2IM8yf6/HwWi6/Lp7dgSG1+qBZ1lUPPTY+dFLPZyt/kul+vuOj6GLZaU
|
||||
s3D66d7TaPCHKWAOnP9RHpic/iXODXVXo1KHJfa0x8fW7I+y7/Gb+5x/m4O0Bz2T
|
||||
BivdrSAuFpXkPqwawlw4CPgI9fc801g83+ZFzD2jJ6qxkEgfnlmf+zGNn5tC4N5j
|
||||
NRTQ+GyHo1w4824SXcSN590wgz8goGJC3QPJxbifvOA8GzQIVzpxHckofOVyqIEq
|
||||
qSnkP2xn4mELqD7HcFnoojZBqFbF2cN+oWQ+niLN+v4qrUncpQI9SVWlyp66S+1T
|
||||
BhBQj2QuX+3B+K27EiDbhNV7EX6xEbGsnB1poMc2aMiz6veybW3GnoM+2ppr8Ko/
|
||||
12Ij7l+ZA44t6PWUfQQbNSbUk/0Yhd9QJ8VQVck+TaS6gtarTbURlSdmHwARAQAB
|
||||
tCl0ZWNub3ZlcnQgKGdpdGlhbikgPHRlY25vdmVydEBwYXJ0aWNsLmlvPokCVAQT
|
||||
AQgAPhYhBI5RfcEuwcw39kI6ihPxNlHJzw1rBQJZS8mCAhsDBQkSzAMABQsJCAcC
|
||||
BhUICQoLAgQWAgMBAh4BAheAAAoJEBPxNlHJzw1rtdYP/22iRX8O2Q++MayPHNx5
|
||||
XHAlMk9mfi5FB1qJwshtlhda7P9U/hOTi227wH+Mzh5dBje4t2DkoHzxlz/Wr4cQ
|
||||
QUJMOYd0OEZY6kpAQkvtyYobIb6zlRQK1koAfNMxewmfZZGTlr16IUVCovGSFvZ+
|
||||
hdYRDEjuHqXjpwBfrxFAy/HCnfY10qSRkJc5w1ypj1IkzlanS+xeRJSDvRTQDAEr
|
||||
zv3xKcMGjCCHaaCP+tyAaViBaUOlvmZdWwg0gwQCuPLqIh0cfDbcg0quciRIpnyp
|
||||
zINmfwngZCwXdIYfAzmCzMHw1J3iOiqfqK0EcpHMsL689VyQSPgsoEHtcOGHYjRL
|
||||
pMPGvRFHtICrnCHENK3IcwFWDGXW+i3zgOlA7g48yYWWvSup+t8I6YT+FeeFlxSO
|
||||
dj1GdeMA0O7gXZ7znLVduokL2Ef4dZjc+3NwBlFov52vwCZwQMAGsMriwEDB2rDZ
|
||||
B7YOvAxlUB/kavtx/oE8fV7mZcuwYg02lq4bozF9xlhjOFaRit6xXnLVi0TuI76c
|
||||
uz67nB9VkWczSLIzCyjNyFpWbx1BMxTYfehZX3+YNajXwG6HdEp9CAYK0u46Guz/
|
||||
Pth67bbNVYyP/cuOIrv/hqQ6xo4mOBMDDxcCEAXx3rwxfbxNM8vlwrMcpITrtNON
|
||||
r41bcxUIfMEDefPm5wnXep8W
|
||||
=szpX
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
|
|
29
basicswap/pgp/keys/wownero_wowario.pgp
Normal file
29
basicswap/pgp/keys/wownero_wowario.pgp
Normal file
|
@ -0,0 +1,29 @@
|
|||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQINBGROehcBEACXWWc6dHqCos1PmKI32iHi0jP3mYM3jU57YxbjwT78QEtEwSqf
|
||||
YklpXkgTYq7jexx2JElfegM6w1sPYarq1y051RjnCgzl32da5I506SMvcJTmXumV
|
||||
Rw6erPeDxAO74PflDSlALgtGOgbKhwwWRudbWgT5hKGkl62qy0mI6GStul0rbT+3
|
||||
gq77DCGyURfe1PG1pymhO5XVz3WGtOa12NvRA+3wGIcqIji2MbtXuOhGMg//kVI5
|
||||
m2vcfHyMMuQ01xUXRu57WxRujYaJ1RB4p86JCbDX3YU2XlzTxGAhqChDLuJGqo54
|
||||
AZMUWDceftXsAoOqH8Hwmm5gFkYSpMt86ZT+umvWygmxohD5k85MuRj4AGagFj/u
|
||||
CMcQjI/SN1UU/Qozg6VL/5FO8aH9IybDzX7eE3j0V/jTweStw1CIUajYgfemWOWl
|
||||
whLPBDflRz/8EEqTN0CaSSaiYiULZUiawBO/bRIiCO2Q6QrAi3KpPUhCwiw/Yecd
|
||||
rAMLH7bytpECDdbNonQ/VMxWwtWJQ87qBtWvHFQxXBKjyuANsKL9X7v3KcYOUdd2
|
||||
fSt7eqE9GDT4DbK6sTmuTpq2TgHXET0cA39+N2zxTh5xFupI/pi2iAHJ6hgIiQnn
|
||||
662TngjGOSFvrTV/51Ua0Vx8OCMJJOcRdOVaYzuzg9DsjVcJin3aRqUh4wARAQAB
|
||||
tCBXb3dhcmlvIDx3b3dhcmlvQHByb3Rvbm1haWwuY29tPokCVAQTAQgAPhYhBKs6
|
||||
L3JYGPz/J5SEHHk1BLRJxpIgBQJkTnoXAhsDBQkHhh77BQsJCAcCBhUKCQgLAgQW
|
||||
AgMBAh4BAheAAAoJEHk1BLRJxpIgwgEP/109vw1WXRh9EaRr3Y1+sBi+/PRQ5TCx
|
||||
UEcP9ru5sQPJ0BsZK8RYw0BNIfDQX9OB1k/AoiBelL+0EoDKvjXmwz9fPUmSVk5r
|
||||
3RzfClXTnxn4HXPKkSGMt4WBUnvohTexK7CPkb9xy+K0Jtx8XF1XiQLDFg2a9lBj
|
||||
IIX2H6aHn4VjdUBv7TrTCAI2Vg0cQUpeJUwyHH+lk0r2WM3zAxzS3Iy2yDDstNT8
|
||||
audXEX4BtJhyEU1m57jwgscrbTtgwYOAsaRLcnUaAFWhbov3IiGInk7N1fkMsuW5
|
||||
HE5RcegSZRS3X4o6O/nmwdSjCEB9weydOCPrtfdbvfvuTiMg/jZBikOk/Sj7FM/D
|
||||
eZKghSHpLbT/V3S76FyIcc/xFkUmR+2fGvCNjJ1Qn2lXTS8xcbyzqR4LZPeUGppV
|
||||
hvriilLnXSjyc60wuD3kmCCo1Zw4tNL8pr09BtVmScUy6eiwca8LLzvbbivqxF1g
|
||||
Mrkkv8yQE0ZwO1kgNSn+PSzUPbwAoklcyN5Rhr5DxZh0UudiH5Jt5WWYeE8O2Uc1
|
||||
si13X575kymGkkeiUcp9WtBkh2uial+RVmTrUTDUTIR2HzT6MAR84/DHlC5dsW8a
|
||||
h4uDUhzeG2cTxuIfZC881UHKL+xT/I3PPuFdLbU5uoWJpXYpxKYulYWd7LA/k4bi
|
||||
JWBrQo7VDvvP
|
||||
=H3wS
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
BIN
basicswap/static/images/coins/Namecoin-20.png
Normal file
BIN
basicswap/static/images/coins/Namecoin-20.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 743 B |
BIN
basicswap/static/images/coins/Namecoin.png
Normal file
BIN
basicswap/static/images/coins/Namecoin.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 4.2 KiB |
|
@ -10,6 +10,7 @@ const COIN_NAME_TO_SYMBOL = {
|
|||
'Firo': 'FIRO',
|
||||
'Dash': 'DASH',
|
||||
'Decred': 'DCR',
|
||||
'Namecoin': 'NMC',
|
||||
'Wownero': 'WOW',
|
||||
'Bitcoin Cash': 'BCH',
|
||||
'Dogecoin': 'DOGE'
|
||||
|
@ -335,13 +336,13 @@ const createBidTableRow = async (bid) => {
|
|||
</a>
|
||||
</div>
|
||||
<div class="monospace text-xs text-gray-500 dark:text-gray-300">
|
||||
<span class="font-semibold">Offer ID:</span>
|
||||
<span class="font-semibold">Offer ID:</span>
|
||||
<a href="/offer/${bid.offer_id}" data-tooltip-target="tooltip-offer-${uniqueId}" class="hover:underline">
|
||||
${formatAddress(bid.offer_id)}
|
||||
</a>
|
||||
</div>
|
||||
<div class="monospace text-xs text-gray-500 dark:text-gray-300">
|
||||
<span class="font-semibold">Bid ID:</span>
|
||||
<span class="font-semibold">Bid ID:</span>
|
||||
<a href="/bid/${bid.bid_id}" data-tooltip-target="tooltip-bid-${uniqueId}" class="hover:underline">
|
||||
${formatAddress(bid.bid_id)}
|
||||
</a>
|
||||
|
@ -366,8 +367,8 @@ const createBidTableRow = async (bid) => {
|
|||
<div class="py-3 px-4 text-center">
|
||||
<div class="flex items-center justify-center">
|
||||
<span class="inline-flex mr-3 align-middle items-center justify-center w-18 h-20 rounded">
|
||||
<img class="h-12"
|
||||
src="/static/images/coins/${bid.coin_from.replace(' ', '-')}.png"
|
||||
<img class="h-12"
|
||||
src="/static/images/coins/${bid.coin_from.replace(' ', '-')}.png"
|
||||
alt="${bid.coin_from}"
|
||||
onerror="this.src='/static/images/coins/default.png'">
|
||||
</span>
|
||||
|
@ -375,15 +376,14 @@ const createBidTableRow = async (bid) => {
|
|||
<path fill-rule="evenodd" d="M12.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-2.293-2.293a1 1 0 010-1.414z"></path>
|
||||
</svg>
|
||||
<span class="inline-flex ml-3 align-middle items-center justify-center w-18 h-20 rounded">
|
||||
<img class="h-12"
|
||||
src="/static/images/coins/${bid.coin_to.replace(' ', '-')}.png"
|
||||
<img class="h-12"
|
||||
src="/static/images/coins/${bid.coin_to.replace(' ', '-')}.png"
|
||||
alt="${bid.coin_to}"
|
||||
onerror="this.src='/static/images/coins/default.png'">
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<!-- You Get Column -->
|
||||
<td class="py-0">
|
||||
<div class="py-3 px-4 text-right">
|
||||
|
@ -410,7 +410,7 @@ const createBidTableRow = async (bid) => {
|
|||
|
||||
<!-- Actions Column -->
|
||||
<td class="py-3 px-4 text-center">
|
||||
<a href="/bid/${bid.bid_id}/accept"
|
||||
<a href="/bid/${bid.bid_id}/accept"
|
||||
class="inline-block w-20 py-1 px-2 font-medium text-center text-sm rounded-md bg-blue-500 text-white border border-blue-500 hover:bg-blue-600 transition duration-200">
|
||||
Accept
|
||||
</a>
|
||||
|
@ -506,13 +506,13 @@ const createDetailsColumn = (bid, identity, uniqueId) => `
|
|||
</a>
|
||||
</div>
|
||||
<div class="monospace text-xs text-gray-500 dark:text-gray-300">
|
||||
<span class="font-semibold">Offer ID:</span>
|
||||
<span class="font-semibold">Offer ID:</span>
|
||||
<a href="/offer/${bid.offer_id}" data-tooltip-target="tooltip-offer-${uniqueId}" class="hover:underline">
|
||||
${formatAddress(bid.offer_id)}
|
||||
</a>
|
||||
</div>
|
||||
<div class="monospace text-xs text-gray-500 dark:text-gray-300">
|
||||
<span class="font-semibold">Bid ID:</span>
|
||||
<span class="font-semibold">Bid ID:</span>
|
||||
<a href="/bid/${bid.bid_id}" data-tooltip-target="tooltip-bid-${uniqueId}" class="hover:underline">
|
||||
${formatAddress(bid.bid_id)}
|
||||
</a>
|
||||
|
|
|
@ -220,7 +220,7 @@ const ApiManager = (function() {
|
|||
.filter(coin => coin.usesCoinGecko)
|
||||
.map(coin => coin.name)
|
||||
.join(',') :
|
||||
'bitcoin,monero,particl,bitcoincash,pivx,firo,dash,litecoin,dogecoin,decred';
|
||||
'bitcoin,monero,particl,bitcoincash,pivx,firo,dash,litecoin,dogecoin,decred,namecoin';
|
||||
|
||||
//console.log('Fetching coin prices for:', coins);
|
||||
const response = await this.fetchCoinPrices(coins);
|
||||
|
@ -254,7 +254,7 @@ const ApiManager = (function() {
|
|||
.filter(coin => coin.usesCoinGecko)
|
||||
.map(coin => getCoinBackendId ? getCoinBackendId(coin.name) : coin.name)
|
||||
.join(',') :
|
||||
'bitcoin,monero,particl,bitcoin-cash,pivx,firo,dash,litecoin,dogecoin,decred';
|
||||
'bitcoin,monero,particl,bitcoin-cash,pivx,firo,dash,litecoin,dogecoin,decred,namecoin';
|
||||
|
||||
const url = `https://api.coingecko.com/api/v3/simple/price?ids=${coins}&vs_currencies=usd&include_24hr_vol=true&include_24hr_change=true`;
|
||||
|
||||
|
|
|
@ -504,13 +504,14 @@ const CacheManager = (function() {
|
|||
'bitcoin': 'BTC',
|
||||
'litecoin': 'LTC',
|
||||
'monero': 'XMR',
|
||||
'wownero': 'WOW',
|
||||
'particl': 'PART',
|
||||
'pivx': 'PIVX',
|
||||
'firo': 'FIRO',
|
||||
'zcoin': 'FIRO',
|
||||
'dash': 'DASH',
|
||||
'decred': 'DCR',
|
||||
'wownero': 'WOW',
|
||||
'namecoin': 'NMR',
|
||||
'bitcoin-cash': 'BCH',
|
||||
'dogecoin': 'DOGE'
|
||||
};
|
||||
|
|
|
@ -72,6 +72,7 @@ const ConfigManager = (function() {
|
|||
{ symbol: 'LTC', name: 'litecoin', usesCryptoCompare: true, usesCoinGecko: true, historicalDays: 30 },
|
||||
{ symbol: 'DOGE', name: 'dogecoin', usesCryptoCompare: true, usesCoinGecko: true, historicalDays: 30 },
|
||||
{ symbol: 'DCR', name: 'decred', usesCryptoCompare: true, usesCoinGecko: true, historicalDays: 30 },
|
||||
{ symbol: 'NMC', name: 'namecoin', usesCryptoCompare: true, usesCoinGecko: true, historicalDays: 30 },
|
||||
{ symbol: 'WOW', name: 'wownero', usesCryptoCompare: false, usesCoinGecko: true, historicalDays: 30 }
|
||||
],
|
||||
|
||||
|
@ -88,6 +89,7 @@ const ConfigManager = (function() {
|
|||
'Zcoin': 'FIRO',
|
||||
'Dash': 'DASH',
|
||||
'Decred': 'DCR',
|
||||
'Namecoin': 'NMC',
|
||||
'Wownero': 'WOW',
|
||||
'Bitcoin Cash': 'BCH',
|
||||
'Dogecoin': 'DOGE'
|
||||
|
@ -105,13 +107,14 @@ const ConfigManager = (function() {
|
|||
'Zcoin': 'Firo',
|
||||
'Dash': 'Dash',
|
||||
'Decred': 'Decred',
|
||||
'Namecoin': 'Namecoin',
|
||||
'Wownero': 'Wownero',
|
||||
'Bitcoin Cash': 'Bitcoin Cash',
|
||||
'Dogecoin': 'Dogecoin'
|
||||
},
|
||||
|
||||
idToName: {
|
||||
1: 'particl', 2: 'bitcoin', 3: 'litecoin', 4: 'decred',
|
||||
1: 'particl', 2: 'bitcoin', 3: 'litecoin', 4: 'decred', 5: 'namecoin',
|
||||
6: 'monero', 7: 'particl blind', 8: 'particl anon',
|
||||
9: 'wownero', 11: 'pivx', 13: 'firo', 17: 'bitcoincash',
|
||||
18: 'dogecoin'
|
||||
|
@ -130,6 +133,7 @@ const ConfigManager = (function() {
|
|||
'litecoin': 'litecoin',
|
||||
'dogecoin': 'dogecoin',
|
||||
'decred': 'decred',
|
||||
'namecoin': 'namecoin',
|
||||
'wownero': 'wownero'
|
||||
}
|
||||
},
|
||||
|
@ -367,6 +371,7 @@ const ConfigManager = (function() {
|
|||
'dash': { usd: null, btc: null },
|
||||
'dogecoin': { usd: null, btc: null },
|
||||
'decred': { usd: null, btc: null },
|
||||
'namecoin': { usd: null, btc: null },
|
||||
'litecoin': { usd: null, btc: null },
|
||||
'particl': { usd: null, btc: null },
|
||||
'pivx': { usd: null, btc: null },
|
||||
|
|
|
@ -35,6 +35,7 @@ const WalletManager = (function() {
|
|||
'Dash': 'DASH',
|
||||
'PIVX': 'PIVX',
|
||||
'Decred': 'DCR',
|
||||
'Namecoin': 'NMC',
|
||||
'Bitcoin Cash': 'BCH'
|
||||
},
|
||||
|
||||
|
@ -49,6 +50,7 @@ const WalletManager = (function() {
|
|||
'DASH': 'dash',
|
||||
'PIVX': 'pivx',
|
||||
'DCR': 'dcr',
|
||||
'NMC': 'nmc',
|
||||
'BCH': 'bch'
|
||||
},
|
||||
|
||||
|
@ -63,6 +65,7 @@ const WalletManager = (function() {
|
|||
'Dash': 'DASH',
|
||||
'PIVX': 'PIVX',
|
||||
'Decred': 'DCR',
|
||||
'Namecoin': 'NMC',
|
||||
'Bitcoin Cash': 'BCH',
|
||||
'Dogecoin': 'DOGE'
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ window.tableRateModule = {
|
|||
'Dash': 'DASH',
|
||||
'PIVX': 'PIVX',
|
||||
'Decred': 'DCR',
|
||||
'Namecoin': 'NMC',
|
||||
'Zano': 'ZANO',
|
||||
'Bitcoin Cash': 'BCH',
|
||||
'Dogecoin': 'DOGE'
|
||||
|
@ -56,9 +57,9 @@ window.tableRateModule = {
|
|||
},
|
||||
|
||||
setCachedValue(key, value, resourceType = null) {
|
||||
const ttl = resourceType ?
|
||||
window.config.cacheConfig.ttlSettings[resourceType] ||
|
||||
window.config.cacheConfig.defaultTTL :
|
||||
const ttl = resourceType ?
|
||||
window.config.cacheConfig.ttlSettings[resourceType] ||
|
||||
window.config.cacheConfig.defaultTTL :
|
||||
900000;
|
||||
|
||||
const item = {
|
||||
|
@ -306,13 +307,14 @@ async function calculateProfitLoss(fromCoin, toCoin, fromAmount, toAmount, isOwn
|
|||
'ltc': 'litecoin',
|
||||
'doge': 'dogecoin',
|
||||
'dcr': 'decred',
|
||||
'nmc': 'namecoin',
|
||||
'wow': 'wownero'
|
||||
};
|
||||
|
||||
if (lowerCoin === 'zcoin') return 'firo';
|
||||
if (lowerCoin === 'bitcoin cash') return 'bitcoin-cash';
|
||||
if (lowerCoin === 'particl anon' || lowerCoin === 'particl blind') return 'particl';
|
||||
|
||||
|
||||
return symbolToName[lowerCoin] || lowerCoin;
|
||||
};
|
||||
|
||||
|
@ -406,7 +408,7 @@ async function fetchLatestPrices() {
|
|||
const coinIds = [
|
||||
'bitcoin', 'particl', 'monero', 'litecoin',
|
||||
'dogecoin', 'firo', 'dash', 'pivx',
|
||||
'decred', 'bitcoincash'
|
||||
'decred', 'namecoin', 'bitcoincash'
|
||||
];
|
||||
|
||||
let processedData = {};
|
||||
|
@ -419,7 +421,7 @@ async function fetchLatestPrices() {
|
|||
if (mainResponse && mainResponse.rates) {
|
||||
Object.entries(mainResponse.rates).forEach(([coinId, price]) => {
|
||||
const normalizedCoinId = coinId === 'bitcoincash' ? 'bitcoin-cash' : coinId.toLowerCase();
|
||||
|
||||
|
||||
processedData[normalizedCoinId] = {
|
||||
usd: price,
|
||||
btc: normalizedCoinId === 'bitcoin' ? 1 : price / (mainResponse.rates.bitcoin || 1)
|
||||
|
@ -453,7 +455,7 @@ async function fetchLatestPrices() {
|
|||
} catch (error) {
|
||||
console.error(`Price fetch attempt ${attempt + 1} failed:`, error);
|
||||
NetworkManager.handleNetworkError(error);
|
||||
|
||||
|
||||
if (attempt < MAX_RETRIES - 1) {
|
||||
const delay = Math.min(500 * Math.pow(2, attempt), 5000);
|
||||
await new Promise(resolve => setTimeout(resolve, delay));
|
||||
|
@ -520,7 +522,7 @@ async function fetchOffers() {
|
|||
originalJsonData = [...jsonData];
|
||||
|
||||
latestPrices = pricesData || getEmptyPriceData();
|
||||
|
||||
|
||||
CacheManager.set('offers_cached', jsonData, 'offers');
|
||||
|
||||
await updateOffersTable();
|
||||
|
@ -1353,7 +1355,7 @@ function createRateColumn(offer, coinFrom, coinTo) {
|
|||
|
||||
const getPriceKey = (coin) => {
|
||||
const lowerCoin = coin.toLowerCase();
|
||||
|
||||
|
||||
const symbolToName = {
|
||||
'btc': 'bitcoin',
|
||||
'xmr': 'monero',
|
||||
|
@ -1365,13 +1367,14 @@ function createRateColumn(offer, coinFrom, coinTo) {
|
|||
'ltc': 'litecoin',
|
||||
'doge': 'dogecoin',
|
||||
'dcr': 'decred',
|
||||
'nmc': 'namecoin',
|
||||
'wow': 'wownero'
|
||||
};
|
||||
|
||||
|
||||
if (lowerCoin === 'zcoin') return 'firo';
|
||||
if (lowerCoin === 'bitcoin cash') return 'bitcoin-cash';
|
||||
if (lowerCoin === 'particl anon' || lowerCoin === 'particl blind') return 'particl';
|
||||
|
||||
|
||||
return symbolToName[lowerCoin] || lowerCoin;
|
||||
};
|
||||
|
||||
|
@ -1655,23 +1658,24 @@ function createTooltipContent(isSentOffers, coinFrom, coinTo, fromAmount, toAmou
|
|||
'ltc': 'litecoin',
|
||||
'doge': 'dogecoin',
|
||||
'dcr': 'decred',
|
||||
'nmc': 'namecoin',
|
||||
'wow': 'wownero'
|
||||
};
|
||||
|
||||
if (lowerCoin === 'zcoin') return 'firo';
|
||||
if (lowerCoin === 'bitcoin cash') return 'bitcoin-cash';
|
||||
if (lowerCoin === 'particl anon' || lowerCoin === 'particl blind') return 'particl';
|
||||
|
||||
|
||||
return symbolToName[lowerCoin] || lowerCoin;
|
||||
};
|
||||
|
||||
|
||||
if (latestPrices && latestPrices['firo'] && !latestPrices['zcoin']) {
|
||||
latestPrices['zcoin'] = JSON.parse(JSON.stringify(latestPrices['firo']));
|
||||
}
|
||||
|
||||
const fromSymbol = getPriceKey(coinFrom);
|
||||
const toSymbol = getPriceKey(coinTo);
|
||||
|
||||
|
||||
let fromPriceUSD = latestPrices && latestPrices[fromSymbol] ? latestPrices[fromSymbol].usd : null;
|
||||
let toPriceUSD = latestPrices && latestPrices[toSymbol] ? latestPrices[toSymbol].usd : null;
|
||||
|
||||
|
@ -1685,7 +1689,7 @@ function createTooltipContent(isSentOffers, coinFrom, coinTo, fromAmount, toAmou
|
|||
isNaN(fromPriceUSD) || isNaN(toPriceUSD)) {
|
||||
return `<p class="font-bold mb-1">Price Information Unavailable</p>
|
||||
<p>Current market prices are temporarily unavailable.</p>
|
||||
<p class="mt-2">You are ${isSentOffers ? 'selling' : 'buying'} ${fromAmount.toFixed(8)} ${coinFrom}
|
||||
<p class="mt-2">You are ${isSentOffers ? 'selling' : 'buying'} ${fromAmount.toFixed(8)} ${coinFrom}
|
||||
for ${toAmount.toFixed(8)} ${coinTo}.</p>
|
||||
<p class="font-bold mt-2">Note:</p>
|
||||
<p>Profit/loss calculations will be available when price data is restored.</p>`;
|
||||
|
@ -1757,13 +1761,14 @@ function createCombinedRateTooltip(offer, coinFrom, coinTo, treatAsSentOffer) {
|
|||
'ltc': 'litecoin',
|
||||
'doge': 'dogecoin',
|
||||
'dcr': 'decred',
|
||||
'nmc': 'namecoin',
|
||||
'wow': 'wownero'
|
||||
};
|
||||
|
||||
if (lowerCoin === 'zcoin') return 'firo';
|
||||
if (lowerCoin === 'bitcoin cash') return 'bitcoin-cash';
|
||||
if (lowerCoin === 'particl anon' || lowerCoin === 'particl blind') return 'particl';
|
||||
|
||||
|
||||
return symbolToName[lowerCoin] || lowerCoin;
|
||||
};
|
||||
|
||||
|
@ -1876,7 +1881,7 @@ function clearFilters() {
|
|||
|
||||
jsonData = [...originalJsonData];
|
||||
currentPage = 1;
|
||||
|
||||
|
||||
const storageKey = isSentOffers ? 'sentOffersTableSettings' : 'networkOffersTableSettings';
|
||||
localStorage.removeItem(storageKey);
|
||||
|
||||
|
@ -2194,7 +2199,7 @@ async function initializeTableAndData() {
|
|||
function loadSavedSettings() {
|
||||
const storageKey = isSentOffers ? 'sentOffersTableSettings' : 'networkOffersTableSettings';
|
||||
const saved = localStorage.getItem(storageKey);
|
||||
|
||||
|
||||
if (saved) {
|
||||
const settings = JSON.parse(saved);
|
||||
|
||||
|
@ -2229,7 +2234,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
NetworkManager.initialize({
|
||||
connectionTestEndpoint: '/json',
|
||||
connectionTestTimeout: 3000,
|
||||
reconnectDelay: 5000,
|
||||
reconnectDelay: 5000,
|
||||
maxReconnectAttempts: 5
|
||||
});
|
||||
window.networkManagerInitialized = true;
|
||||
|
@ -2252,7 +2257,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
});
|
||||
|
||||
const tableLoadPromise = initializeTableAndData();
|
||||
|
||||
|
||||
WebSocketManager.initialize({
|
||||
debug: false
|
||||
});
|
||||
|
@ -2262,7 +2267,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
if (!NetworkManager.isOnline()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const endpoint = isSentOffers ? '/json/sentoffers' : '/json/offers';
|
||||
const response = await fetch(endpoint);
|
||||
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
|
||||
|
@ -2349,7 +2354,7 @@ async function cleanup() {
|
|||
lastRefreshTime = null;
|
||||
|
||||
const domRefs = [
|
||||
'offersBody', 'filterForm', 'prevPageButton', 'nextPageButton',
|
||||
'offersBody', 'filterForm', 'prevPageButton', 'nextPageButton',
|
||||
'currentPageSpan', 'totalPagesSpan', 'lastRefreshTimeSpan', 'newEntriesCountSpan'
|
||||
];
|
||||
|
||||
|
|
|
@ -548,7 +548,7 @@ const ui = {
|
|||
},
|
||||
|
||||
setActiveContainer: (containerId) => {
|
||||
const containerIds = ['btc', 'xmr', 'part', 'pivx', 'firo', 'dash', 'ltc', 'doge', 'eth', 'dcr', 'zano', 'wow', 'bch'].map(id => `${id}-container`);
|
||||
const containerIds = ['btc', 'xmr', 'part', 'pivx', 'firo', 'dash', 'ltc', 'doge', 'eth', 'dcr', 'nmc', 'zano', 'wow', 'bch'].map(id => `${id}-container`);
|
||||
containerIds.forEach(id => {
|
||||
const container = document.getElementById(id);
|
||||
if (container) {
|
||||
|
|
|
@ -10,6 +10,7 @@ const COIN_NAME_TO_SYMBOL = {
|
|||
'Firo': 'FIRO',
|
||||
'Dash': 'DASH',
|
||||
'Decred': 'DCR',
|
||||
'Namecoin': 'NMC',
|
||||
'Wownero': 'WOW',
|
||||
'Bitcoin Cash': 'BCH',
|
||||
'Dogecoin': 'DOGE'
|
||||
|
@ -383,8 +384,8 @@ const createSwapTableRow = async (swap) => {
|
|||
<div class="py-3 px-4 text-center">
|
||||
<div class="flex items-center justify-center">
|
||||
<span class="inline-flex mr-3 align-middle items-center justify-center w-18 h-20 rounded">
|
||||
<img class="h-12"
|
||||
src="/static/images/coins/${swap.coin_from.replace(' ', '-')}.png"
|
||||
<img class="h-12"
|
||||
src="/static/images/coins/${swap.coin_from.replace(' ', '-')}.png"
|
||||
alt="${swap.coin_from}"
|
||||
onerror="this.src='/static/images/coins/default.png'">
|
||||
</span>
|
||||
|
@ -392,8 +393,8 @@ const createSwapTableRow = async (swap) => {
|
|||
<path fill-rule="evenodd" d="M12.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-2.293-2.293a1 1 0 010-1.414z"></path>
|
||||
</svg>
|
||||
<span class="inline-flex ml-3 align-middle items-center justify-center w-18 h-20 rounded">
|
||||
<img class="h-12"
|
||||
src="/static/images/coins/${swap.coin_to.replace(' ', '-')}.png"
|
||||
<img class="h-12"
|
||||
src="/static/images/coins/${swap.coin_to.replace(' ', '-')}.png"
|
||||
alt="${swap.coin_to}"
|
||||
onerror="this.src='/static/images/coins/default.png'">
|
||||
</span>
|
||||
|
@ -421,7 +422,7 @@ const createSwapTableRow = async (swap) => {
|
|||
|
||||
<!-- Actions Column -->
|
||||
<td class="py-3 px-4 text-center">
|
||||
<a href="/bid/${swap.bid_id}"
|
||||
<a href="/bid/${swap.bid_id}"
|
||||
class="inline-block w-20 py-1 px-2 font-medium text-center text-sm rounded-md bg-blue-500 text-white border border-blue-500 hover:bg-blue-600 transition duration-200">
|
||||
Details
|
||||
</a>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<div class="relative py-8 px-8 bg-coolGray-900 dark:bg-gray-500 rounded-md overflow-hidden">
|
||||
<img class="absolute z-10 left-4 top-4" src="/static/images/elements/dots-red.svg" alt="">
|
||||
<img class="absolute z-10 right-4 bottom-4" src="/static/images/elements/dots-red.svg" alt="">
|
||||
<img class="absolute h-64 left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2 object-cover"
|
||||
<img class="absolute h-64 left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2 object-cover"
|
||||
src="/static/images/elements/wave.svg" alt="">
|
||||
<div class="relative z-20 flex flex-wrap items-center -m-3">
|
||||
<div class="w-full md:w-1/2 p-3">
|
||||
|
@ -21,7 +21,7 @@
|
|||
<p class="font-normal text-coolGray-200 dark:text-white">{{ page_type_description }}</p>
|
||||
</div>
|
||||
<div class="w-full md:w-1/2 p-3 flex justify-end items-center hidden">
|
||||
<a id="refresh" href="/newoffer"
|
||||
<a id="refresh" href="/newoffer"
|
||||
class="rounded-full flex items-center justify-center px-4 py-2 bg-blue-500 hover:bg-green-600 hover:border-green-600 font-medium text-sm text-white border border-blue-500 rounded-md focus:ring-0 focus:outline-none">
|
||||
{{ place_new_offer_svg | safe }}
|
||||
<span>Place new Offer</span>
|
||||
|
@ -136,12 +136,13 @@
|
|||
'ETH': {'name': 'Ethereum', 'symbol': 'ETH', 'image': 'Ethereum.png', 'show': false},
|
||||
'DOGE': {'name': 'Dogecoin', 'symbol': 'DOGE', 'image': 'Dogecoin.png', 'show': true},
|
||||
'DCR': {'name': 'Decred', 'symbol': 'DCR', 'image': 'Decred.png', 'show': true},
|
||||
'NMC': {'name': 'Namecoin', 'symbol': 'NMC', 'image': 'Namecoin.png', 'show': true},
|
||||
'ZANO': {'name': 'Zano', 'symbol': 'ZANO', 'image': 'Zano.png', 'show': false},
|
||||
'WOW': {'name': 'Wownero', 'symbol': 'WOW', 'image': 'Wownero.png', 'show': true}
|
||||
}
|
||||
%}
|
||||
{% set custom_order = ['BTC', 'ETH', 'XMR', 'PART', 'LTC', 'BCH', 'FIRO', 'PIVX', 'DASH', 'DOGE', 'DCR', 'ZANO', 'WOW'] %}
|
||||
|
||||
{% set custom_order = ['BTC', 'ETH', 'XMR', 'PART', 'LTC', 'BCH', 'FIRO', 'PIVX', 'DASH', 'DOGE', 'DCR', 'NMC', 'ZANO', 'WOW'] %}
|
||||
|
||||
{% if enabled_chart_coins is string %}
|
||||
{% if enabled_chart_coins == "" %}
|
||||
{% set display_coins = coin_data.keys()|list %}
|
||||
|
|
|
@ -34,6 +34,11 @@ from tests.basicswap.common import (
|
|||
PIVX_BASE_PORT,
|
||||
BTC_USE_DESCRIPTORS,
|
||||
)
|
||||
from tests.basicswap.extended.test_nmc import (
|
||||
NMC_BASE_PORT,
|
||||
NMC_BASE_RPC_PORT,
|
||||
NMC_BASE_TOR_PORT,
|
||||
)
|
||||
from tests.basicswap.extended.test_dcr import (
|
||||
DCR_BASE_PORT,
|
||||
DCR_BASE_RPC_PORT,
|
||||
|
@ -50,13 +55,6 @@ from tests.basicswap.extended.test_doge import (
|
|||
import basicswap.config as cfg
|
||||
import basicswap.bin.run as runSystem
|
||||
|
||||
XMR_BASE_P2P_PORT = 17792
|
||||
XMR_BASE_RPC_PORT = 29798
|
||||
XMR_BASE_WALLET_RPC_PORT = 29998
|
||||
|
||||
FIRO_BASE_PORT = 34832
|
||||
FIRO_BASE_RPC_PORT = 35832
|
||||
FIRO_RPC_PORT_BASE = int(os.getenv("FIRO_RPC_PORT_BASE", FIRO_BASE_RPC_PORT))
|
||||
|
||||
TEST_PATH = os.path.expanduser(os.getenv("TEST_PATH", "~/test_basicswap1"))
|
||||
|
||||
|
@ -68,7 +66,21 @@ BITCOIN_RPC_PORT_BASE = int(os.getenv("BITCOIN_RPC_PORT_BASE", BTC_BASE_RPC_PORT
|
|||
BITCOIN_TOR_PORT_BASE = int(os.getenv("BITCOIN_TOR_PORT_BASE", BTC_BASE_TOR_PORT))
|
||||
|
||||
LITECOIN_RPC_PORT_BASE = int(os.getenv("LITECOIN_RPC_PORT_BASE", LTC_BASE_RPC_PORT))
|
||||
|
||||
DECRED_RPC_PORT_BASE = int(os.getenv("DECRED_RPC_PORT_BASE", DCR_BASE_RPC_PORT))
|
||||
|
||||
NAMECOIN_PORT_BASE = int(os.getenv("NAMECOIN_PORT_BASE", NMC_BASE_PORT))
|
||||
NAMECOIN_RPC_PORT_BASE = int(os.getenv("NAMECOIN_RPC_PORT_BASE", NMC_BASE_RPC_PORT))
|
||||
NAMECOIN_TOR_PORT_BASE = int(os.getenv("NAMECOIN_TOR_PORT_BASE", NMC_BASE_TOR_PORT))
|
||||
|
||||
XMR_BASE_P2P_PORT = 17792
|
||||
XMR_BASE_RPC_PORT = 29798
|
||||
XMR_BASE_WALLET_RPC_PORT = 29998
|
||||
|
||||
FIRO_BASE_PORT = 34832
|
||||
FIRO_BASE_RPC_PORT = 35832
|
||||
FIRO_RPC_PORT_BASE = int(os.getenv("FIRO_RPC_PORT_BASE", FIRO_BASE_RPC_PORT))
|
||||
|
||||
BITCOINCASH_RPC_PORT_BASE = int(
|
||||
os.getenv("BITCOINCASH_RPC_PORT_BASE", BCH_BASE_RPC_PORT)
|
||||
)
|
||||
|
@ -130,19 +142,21 @@ def run_prepare(
|
|||
os.environ["BTC_RPC_PORT"] = str(BITCOIN_RPC_PORT_BASE)
|
||||
os.environ["BTC_PORT"] = str(BITCOIN_PORT_BASE)
|
||||
os.environ["BTC_USE_DESCRIPTORS"] = str(BTC_USE_DESCRIPTORS)
|
||||
os.environ["BTC_ONION_PORT"] = str(BITCOIN_TOR_PORT_BASE)
|
||||
os.environ["LTC_RPC_PORT"] = str(LITECOIN_RPC_PORT_BASE)
|
||||
os.environ["DCR_RPC_PORT"] = str(DECRED_RPC_PORT_BASE)
|
||||
os.environ["DCR_RPC_PWD"] = "dcr_pwd"
|
||||
os.environ["NMC_RPC_PORT"] = str(NAMECOIN_RPC_PORT_BASE)
|
||||
os.environ["NMC_PORT"] = str(NMC_BASE_PORT)
|
||||
os.environ["NMC_ONION_PORT"] = str(NAMECOIN_TOR_PORT_BASE)
|
||||
os.environ["XMR_RPC_USER"] = "xmr_user"
|
||||
os.environ["XMR_RPC_PWD"] = "xmr_pwd"
|
||||
os.environ["FIRO_RPC_PORT"] = str(FIRO_RPC_PORT_BASE)
|
||||
os.environ["BCH_PORT"] = str(BCH_BASE_PORT)
|
||||
os.environ["BCH_RPC_PORT"] = str(BITCOINCASH_RPC_PORT_BASE)
|
||||
os.environ["DOGE_PORT"] = str(DOGE_BASE_PORT)
|
||||
os.environ["DOGE_RPC_PORT"] = str(DOGECOIN_RPC_PORT_BASE)
|
||||
|
||||
os.environ["XMR_RPC_USER"] = "xmr_user"
|
||||
os.environ["XMR_RPC_PWD"] = "xmr_pwd"
|
||||
|
||||
os.environ["DCR_RPC_PWD"] = "dcr_pwd"
|
||||
|
||||
import basicswap.bin.prepare as prepareSystem
|
||||
|
||||
# Hack: Reload module to set env vars as the basicswap_prepare module is initialised if imported from elsewhere earlier
|
||||
|
@ -320,6 +334,62 @@ def run_prepare(
|
|||
with open(config_filename, "a") as fp:
|
||||
fp.write("enablevoting=1\n")
|
||||
|
||||
if "namecoin" in coins_array:
|
||||
# Pruned nodes don't provide blocks
|
||||
config_filename = os.path.join(datadir_path, "namecoin", "namecoin.conf")
|
||||
with open(config_filename, "r") as fp:
|
||||
lines = fp.readlines()
|
||||
with open(config_filename, "w") as fp:
|
||||
for line in lines:
|
||||
if not line.startswith("prune"):
|
||||
fp.write(line)
|
||||
# fp.write("bind=127.0.0.1\n") # Causes BTC v28 to try and bind to bind=127.0.0.1:8444, even with a bind...=onion present
|
||||
# listenonion=0 does not stop the node from trying to bind to the tor port
|
||||
# https://github.com/bitcoin/bitcoin/issues/22726
|
||||
fp.write(
|
||||
"bind=127.0.0.1:{}=onion\n".format(
|
||||
NAMECOIN_TOR_PORT_BASE + node_id + port_ofs
|
||||
)
|
||||
)
|
||||
fp.write("dnsseed=0\n")
|
||||
fp.write("discover=0\n")
|
||||
fp.write("listenonion=0\n")
|
||||
fp.write("upnp=0\n")
|
||||
if use_rpcauth:
|
||||
salt = generate_salt(16)
|
||||
rpc_user = "test_nmc_" + str(node_id)
|
||||
rpc_pass = "test_nmc_pwd_" + str(node_id)
|
||||
fp.write(
|
||||
"rpcauth={}:{}${}\n".format(
|
||||
rpc_user, salt, password_to_hmac(salt, rpc_pass)
|
||||
)
|
||||
)
|
||||
settings["chainclients"]["namecoin"]["rpcuser"] = rpc_user
|
||||
settings["chainclients"]["namecoin"]["rpcpassword"] = rpc_pass
|
||||
for ip in range(num_nodes):
|
||||
if ip != node_id:
|
||||
fp.write(
|
||||
"connect=127.0.0.1:{}\n".format(
|
||||
NAMECOIN_PORT_BASE + ip + port_ofs
|
||||
)
|
||||
)
|
||||
for opt in EXTRA_CONFIG_JSON.get("ncm{}".format(node_id), []):
|
||||
fp.write(opt + "\n")
|
||||
|
||||
if "monero" in coins_array:
|
||||
with open(os.path.join(datadir_path, "monero", "monerod.conf"), "a") as fp:
|
||||
fp.write("p2p-bind-ip=127.0.0.1\n")
|
||||
fp.write(
|
||||
"p2p-bind-port={}\n".format(XMR_BASE_P2P_PORT + node_id + port_ofs)
|
||||
)
|
||||
for ip in range(num_nodes):
|
||||
if ip != node_id:
|
||||
fp.write(
|
||||
"add-exclusive-node=127.0.0.1:{}\n".format(
|
||||
XMR_BASE_P2P_PORT + ip + port_ofs
|
||||
)
|
||||
)
|
||||
|
||||
if "pivx" in coins_array:
|
||||
# Pruned nodes don't provide blocks
|
||||
config_filename = os.path.join(datadir_path, "pivx", "pivx.conf")
|
||||
|
@ -388,20 +458,6 @@ def run_prepare(
|
|||
for opt in EXTRA_CONFIG_JSON.get("firo{}".format(node_id), []):
|
||||
fp.write(opt + "\n")
|
||||
|
||||
if "monero" in coins_array:
|
||||
with open(os.path.join(datadir_path, "monero", "monerod.conf"), "a") as fp:
|
||||
fp.write("p2p-bind-ip=127.0.0.1\n")
|
||||
fp.write(
|
||||
"p2p-bind-port={}\n".format(XMR_BASE_P2P_PORT + node_id + port_ofs)
|
||||
)
|
||||
for ip in range(num_nodes):
|
||||
if ip != node_id:
|
||||
fp.write(
|
||||
"add-exclusive-node=127.0.0.1:{}\n".format(
|
||||
XMR_BASE_P2P_PORT + ip + port_ofs
|
||||
)
|
||||
)
|
||||
|
||||
if "bitcoincash" in coins_array:
|
||||
config_filename = os.path.join(datadir_path, "bitcoincash", "bitcoin.conf")
|
||||
with open(config_filename, "r") as fp:
|
||||
|
|
|
@ -138,7 +138,6 @@ def run_test_success_path(self, coin_from: Coins, coin_to: Coins):
|
|||
|
||||
# Verify lock tx spends are found in the expected wallets
|
||||
bid, offer = swap_clients[node_from].getBidAndOffer(bid_id)
|
||||
max_fee: int = 10000
|
||||
itx_spend = bid.initiate_tx.spend_txid.hex()
|
||||
node_to_ci_from = swap_clients[node_to].ci(coin_from)
|
||||
wtx = node_to_ci_from.rpc_wallet(
|
||||
|
@ -147,7 +146,9 @@ def run_test_success_path(self, coin_from: Coins, coin_to: Coins):
|
|||
itx_spend,
|
||||
],
|
||||
)
|
||||
assert amt_swap - node_to_ci_from.make_int(wtx["details"][0]["amount"]) < max_fee
|
||||
assert (
|
||||
amt_swap - node_to_ci_from.make_int(wtx["details"][0]["amount"]) < self.max_fee
|
||||
)
|
||||
|
||||
node_from_ci_to = swap_clients[node_from].ci(coin_to)
|
||||
ptx_spend = bid.participate_tx.spend_txid.hex()
|
||||
|
@ -158,7 +159,8 @@ def run_test_success_path(self, coin_from: Coins, coin_to: Coins):
|
|||
],
|
||||
)
|
||||
assert (
|
||||
bid.amount_to - node_from_ci_to.make_int(wtx["details"][0]["amount"]) < max_fee
|
||||
bid.amount_to - node_from_ci_to.make_int(wtx["details"][0]["amount"])
|
||||
< self.max_fee
|
||||
)
|
||||
|
||||
js_0 = read_json_api(1800 + node_from)
|
||||
|
@ -235,7 +237,6 @@ def run_test_bad_ptx(self, coin_from: Coins, coin_to: Coins):
|
|||
|
||||
# Verify lock tx spends are found in the expected wallets
|
||||
bid, offer = swap_clients[node_from].getBidAndOffer(bid_id)
|
||||
max_fee: int = 10000
|
||||
itx_spend = bid.initiate_tx.spend_txid.hex()
|
||||
node_from_ci_from = swap_clients[node_from].ci(coin_from)
|
||||
wtx = node_from_ci_from.rpc_wallet(
|
||||
|
@ -244,7 +245,10 @@ def run_test_bad_ptx(self, coin_from: Coins, coin_to: Coins):
|
|||
itx_spend,
|
||||
],
|
||||
)
|
||||
assert amt_swap - node_from_ci_from.make_int(wtx["details"][0]["amount"]) < max_fee
|
||||
assert (
|
||||
amt_swap - node_from_ci_from.make_int(wtx["details"][0]["amount"])
|
||||
< self.max_fee
|
||||
)
|
||||
|
||||
node_to_ci_to = swap_clients[node_to].ci(coin_to)
|
||||
bid, offer = swap_clients[node_to].getBidAndOffer(bid_id)
|
||||
|
@ -255,7 +259,10 @@ def run_test_bad_ptx(self, coin_from: Coins, coin_to: Coins):
|
|||
ptx_spend,
|
||||
],
|
||||
)
|
||||
assert bid.amount_to - node_to_ci_to.make_int(wtx["details"][0]["amount"]) < max_fee
|
||||
assert (
|
||||
bid.amount_to - node_to_ci_to.make_int(wtx["details"][0]["amount"])
|
||||
< self.max_fee
|
||||
)
|
||||
|
||||
bid_id_hex = bid_id.hex()
|
||||
path = f"bids/{bid_id_hex}/states"
|
||||
|
@ -338,7 +345,6 @@ def run_test_itx_refund(self, coin_from: Coins, coin_to: Coins):
|
|||
|
||||
# Verify lock tx spends are found in the expected wallets
|
||||
bid, offer = swap_clients[node_from].getBidAndOffer(bid_id)
|
||||
max_fee: int = 10000
|
||||
itx_spend = bid.initiate_tx.spend_txid.hex()
|
||||
node_from_ci_from = swap_clients[node_from].ci(coin_from)
|
||||
wtx = node_from_ci_from.rpc_wallet(
|
||||
|
@ -348,7 +354,8 @@ def run_test_itx_refund(self, coin_from: Coins, coin_to: Coins):
|
|||
],
|
||||
)
|
||||
assert (
|
||||
swap_value - node_from_ci_from.make_int(wtx["details"][0]["amount"]) < max_fee
|
||||
swap_value - node_from_ci_from.make_int(wtx["details"][0]["amount"])
|
||||
< self.max_fee
|
||||
)
|
||||
|
||||
node_from_ci_to = swap_clients[node_from].ci(coin_to)
|
||||
|
@ -360,7 +367,8 @@ def run_test_itx_refund(self, coin_from: Coins, coin_to: Coins):
|
|||
],
|
||||
)
|
||||
assert (
|
||||
bid.amount_to - node_from_ci_to.make_int(wtx["details"][0]["amount"]) < max_fee
|
||||
bid.amount_to - node_from_ci_to.make_int(wtx["details"][0]["amount"])
|
||||
< self.max_fee
|
||||
)
|
||||
|
||||
|
||||
|
@ -425,7 +433,6 @@ def run_test_ads_success_path(self, coin_from: Coins, coin_to: Coins):
|
|||
bid, xmr_swap = swap_clients[id_offerer].getXmrBid(bid_id)
|
||||
|
||||
node_from_ci_to = swap_clients[0].ci(coin_to)
|
||||
max_fee: int = 10000
|
||||
if node_from_ci_to.coin_type() in (Coins.XMR, Coins.WOW):
|
||||
pass
|
||||
else:
|
||||
|
@ -437,7 +444,7 @@ def run_test_ads_success_path(self, coin_from: Coins, coin_to: Coins):
|
|||
)
|
||||
assert (
|
||||
bid.amount_to - node_from_ci_to.make_int(wtx["details"][0]["amount"])
|
||||
< max_fee
|
||||
< self.max_fee
|
||||
)
|
||||
|
||||
node_to_ci_from = swap_clients[1].ci(coin_from)
|
||||
|
@ -451,7 +458,8 @@ def run_test_ads_success_path(self, coin_from: Coins, coin_to: Coins):
|
|||
],
|
||||
)
|
||||
assert (
|
||||
bid.amount - node_to_ci_from.make_int(wtx["details"][0]["amount"]) < max_fee
|
||||
bid.amount - node_to_ci_from.make_int(wtx["details"][0]["amount"])
|
||||
< self.max_fee
|
||||
)
|
||||
|
||||
bid_id_hex = bid_id.hex()
|
||||
|
@ -550,7 +558,6 @@ def run_test_ads_both_refund(
|
|||
bid, xmr_swap = swap_clients[id_bidder].getXmrBid(bid_id)
|
||||
|
||||
node_from_ci_from = swap_clients[0].ci(coin_from)
|
||||
max_fee: int = 10000
|
||||
if node_from_ci_from.coin_type() in (Coins.XMR, Coins.WOW):
|
||||
pass
|
||||
else:
|
||||
|
@ -562,7 +569,7 @@ def run_test_ads_both_refund(
|
|||
)
|
||||
assert (
|
||||
bid.amount - node_from_ci_from.make_int(wtx["details"][0]["amount"])
|
||||
< max_fee
|
||||
< self.max_fee
|
||||
)
|
||||
|
||||
node_to_ci_to = swap_clients[1].ci(coin_to)
|
||||
|
@ -577,7 +584,7 @@ def run_test_ads_both_refund(
|
|||
)
|
||||
assert (
|
||||
bid.amount_to - node_to_ci_to.make_int(wtx["details"][0]["amount"])
|
||||
< max_fee
|
||||
< self.max_fee
|
||||
)
|
||||
|
||||
bid_id_hex = bid_id.hex()
|
||||
|
@ -720,6 +727,7 @@ class Test(BaseTest):
|
|||
start_xmr_nodes = True
|
||||
dcr_mining_addr = "SsYbXyjkKAEXXcGdFgr4u4bo4L8RkCxwQpH"
|
||||
extra_wait_time = 0
|
||||
max_fee: int = 10000
|
||||
|
||||
hex_seeds = [
|
||||
"e8574b2a94404ee62d8acc0258cab4c0defcfab8a5dfc2f4954c1f9d7e09d72a",
|
||||
|
|
|
@ -11,78 +11,58 @@ basicswap]$ python tests/basicswap/extended/test_nmc.py
|
|||
|
||||
"""
|
||||
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import signal
|
||||
import random
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
import unittest
|
||||
|
||||
import basicswap.config as cfg
|
||||
from basicswap.basicswap import (
|
||||
BasicSwap,
|
||||
Coins,
|
||||
SwapTypes,
|
||||
BidStates,
|
||||
TxStates,
|
||||
)
|
||||
from basicswap.util import (
|
||||
COIN,
|
||||
)
|
||||
from basicswap.basicswap_util import (
|
||||
TxLockTypes,
|
||||
)
|
||||
from basicswap.util.address import (
|
||||
toWIF,
|
||||
)
|
||||
from basicswap.rpc import (
|
||||
callrpc_cli,
|
||||
)
|
||||
from basicswap.contrib.key import (
|
||||
ECKey,
|
||||
)
|
||||
from basicswap.http_server import (
|
||||
HttpThread,
|
||||
)
|
||||
from tests.basicswap.util import (
|
||||
read_json_api,
|
||||
)
|
||||
from tests.basicswap.common import (
|
||||
checkForks,
|
||||
stopDaemons,
|
||||
wait_for_offer,
|
||||
wait_for_bid,
|
||||
wait_for_bid_tx_state,
|
||||
wait_for_in_progress,
|
||||
TEST_HTTP_HOST,
|
||||
TEST_HTTP_PORT,
|
||||
BASE_PORT,
|
||||
BASE_RPC_PORT,
|
||||
BASE_ZMQ_PORT,
|
||||
PREFIX_SECRET_KEY_REGTEST,
|
||||
waitForRPC,
|
||||
toBool,
|
||||
)
|
||||
from basicswap.bin.run import startDaemon
|
||||
from basicswap.contrib.rpcauth import generate_salt, password_to_hmac
|
||||
from tests.basicswap.common import (
|
||||
stopDaemons,
|
||||
waitForRPC,
|
||||
make_rpc_func,
|
||||
)
|
||||
|
||||
from tests.basicswap.test_btc_xmr import BasicSwapTest, test_delay_event
|
||||
from tests.basicswap.test_xmr import NUM_NODES
|
||||
from tests.basicswap.extended.test_dcr import (
|
||||
run_test_success_path,
|
||||
run_test_bad_ptx,
|
||||
run_test_itx_refund,
|
||||
)
|
||||
|
||||
|
||||
logger = logging.getLogger()
|
||||
logger.level = logging.DEBUG
|
||||
logger = logging.getLogger("BSX Tests")
|
||||
|
||||
if not len(logger.handlers):
|
||||
logger.addHandler(logging.StreamHandler(sys.stdout))
|
||||
|
||||
NUM_NODES = 3
|
||||
NMC_NODE = 3
|
||||
BTC_NODE = 4
|
||||
|
||||
delay_event = threading.Event()
|
||||
stop_test = False
|
||||
NAMECOIN_BINDIR = os.path.expanduser(
|
||||
os.getenv("NAMECOIN_BINDIR", os.path.join(cfg.DEFAULT_TEST_BINDIR, "namecoin"))
|
||||
)
|
||||
NAMECOIND = os.getenv("NAMECOIND", "namecoind" + cfg.bin_suffix)
|
||||
NAMECOIN_CLI = os.getenv("NAMECOIN_CLI", "namecoin-cli" + cfg.bin_suffix)
|
||||
NAMECOIN_TX = os.getenv("NAMECOIN_TX", "namecoin-tx" + cfg.bin_suffix)
|
||||
|
||||
NMC_USE_DESCRIPTORS = toBool(os.getenv("NMC_USE_DESCRIPTORS", True))
|
||||
|
||||
NMC_BASE_PORT = 8136
|
||||
NMC_BASE_RPC_PORT = 8146
|
||||
NMC_BASE_TOR_PORT = 8156
|
||||
|
||||
|
||||
def prepareOtherDir(datadir, nodeId, conf_file="namecoin.conf"):
|
||||
node_dir = os.path.join(datadir, str(nodeId))
|
||||
def prepareNMCDataDir(datadir, nodeId, conf_file="namecoin.conf"):
|
||||
node_dir = os.path.join(datadir, "nmc_" + str(nodeId))
|
||||
if not os.path.exists(node_dir):
|
||||
os.makedirs(node_dir)
|
||||
filePath = os.path.join(node_dir, conf_file)
|
||||
|
@ -90,8 +70,17 @@ def prepareOtherDir(datadir, nodeId, conf_file="namecoin.conf"):
|
|||
with open(filePath, "w+") as fp:
|
||||
fp.write("regtest=1\n")
|
||||
fp.write("[regtest]\n")
|
||||
fp.write("port=" + str(BASE_PORT + nodeId) + "\n")
|
||||
fp.write("rpcport=" + str(BASE_RPC_PORT + nodeId) + "\n")
|
||||
|
||||
fp.write("port=" + str(NMC_BASE_PORT + nodeId) + "\n")
|
||||
fp.write("rpcport=" + str(NMC_BASE_RPC_PORT + nodeId) + "\n")
|
||||
salt = generate_salt(16)
|
||||
fp.write(
|
||||
"rpcauth={}:{}${}\n".format(
|
||||
"test" + str(nodeId),
|
||||
salt,
|
||||
password_to_hmac(salt, "test_pass" + str(nodeId)),
|
||||
)
|
||||
)
|
||||
|
||||
fp.write("daemon=0\n")
|
||||
fp.write("printtoconsole=0\n")
|
||||
|
@ -99,595 +88,182 @@ def prepareOtherDir(datadir, nodeId, conf_file="namecoin.conf"):
|
|||
fp.write("discover=0\n")
|
||||
fp.write("listenonion=0\n")
|
||||
fp.write("bind=127.0.0.1\n")
|
||||
fp.write("findpeers=0\n")
|
||||
fp.write("debug=1\n")
|
||||
fp.write("debugexclude=libevent\n")
|
||||
|
||||
fp.write("fallbackfee=0.01\n")
|
||||
fp.write("acceptnonstdtxn=0\n")
|
||||
|
||||
if conf_file == "bitcoin.conf":
|
||||
fp.write("wallet=wallet.dat\n")
|
||||
|
||||
|
||||
def prepareDir(datadir, nodeId, network_key, network_pubkey):
|
||||
node_dir = os.path.join(datadir, str(nodeId))
|
||||
if not os.path.exists(node_dir):
|
||||
os.makedirs(node_dir)
|
||||
filePath = os.path.join(node_dir, "particl.conf")
|
||||
|
||||
with open(filePath, "w+") as fp:
|
||||
fp.write("regtest=1\n")
|
||||
fp.write("[regtest]\n")
|
||||
fp.write("port=" + str(BASE_PORT + nodeId) + "\n")
|
||||
fp.write("rpcport=" + str(BASE_RPC_PORT + nodeId) + "\n")
|
||||
|
||||
fp.write("daemon=0\n")
|
||||
fp.write("printtoconsole=0\n")
|
||||
fp.write("server=1\n")
|
||||
fp.write("discover=0\n")
|
||||
fp.write("listenonion=0\n")
|
||||
fp.write("bind=127.0.0.1\n")
|
||||
fp.write("findpeers=0\n")
|
||||
fp.write("debug=1\n")
|
||||
fp.write("debugexclude=libevent\n")
|
||||
fp.write("zmqpubsmsg=tcp://127.0.0.1:" + str(BASE_ZMQ_PORT + nodeId) + "\n")
|
||||
fp.write("wallet=wallet.dat\n")
|
||||
fp.write("fallbackfee=0.01\n")
|
||||
|
||||
fp.write("acceptnonstdtxn=0\n")
|
||||
fp.write("minstakeinterval=5\n")
|
||||
fp.write("smsgsregtestadjust=0\n")
|
||||
fp.write("deprecatedrpc=create_bdb\n")
|
||||
fp.write("addresstype=bech32\n")
|
||||
fp.write("changetype=bech32\n")
|
||||
|
||||
for i in range(0, NUM_NODES):
|
||||
if nodeId == i:
|
||||
continue
|
||||
fp.write("addnode=127.0.0.1:%d\n" % (BASE_PORT + i))
|
||||
|
||||
if nodeId < 2:
|
||||
fp.write("spentindex=1\n")
|
||||
fp.write("txindex=1\n")
|
||||
|
||||
basicswap_dir = os.path.join(datadir, str(nodeId), "basicswap")
|
||||
if not os.path.exists(basicswap_dir):
|
||||
os.makedirs(basicswap_dir)
|
||||
|
||||
nmcdatadir = os.path.join(datadir, str(NMC_NODE))
|
||||
btcdatadir = os.path.join(datadir, str(BTC_NODE))
|
||||
settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME)
|
||||
settings = {
|
||||
"debug": True,
|
||||
"zmqhost": "tcp://127.0.0.1",
|
||||
"zmqport": BASE_ZMQ_PORT + nodeId,
|
||||
"htmlhost": "127.0.0.1",
|
||||
"htmlport": 12700 + nodeId,
|
||||
"network_key": network_key,
|
||||
"network_pubkey": network_pubkey,
|
||||
"chainclients": {
|
||||
"particl": {
|
||||
"connection_type": "rpc",
|
||||
"manage_daemon": False,
|
||||
"rpcport": BASE_RPC_PORT + nodeId,
|
||||
"datadir": node_dir,
|
||||
"bindir": cfg.PARTICL_BINDIR,
|
||||
"blocks_confirmed": 2, # Faster testing
|
||||
},
|
||||
"namecoin": {
|
||||
"connection_type": "rpc",
|
||||
"manage_daemon": False,
|
||||
"rpcport": BASE_RPC_PORT + NMC_NODE,
|
||||
"datadir": nmcdatadir,
|
||||
"bindir": cfg.NAMECOIN_BINDIR,
|
||||
"use_csv": False,
|
||||
# 'use_segwit': True,
|
||||
},
|
||||
"bitcoin": {
|
||||
"connection_type": "rpc",
|
||||
"manage_daemon": False,
|
||||
"rpcport": BASE_RPC_PORT + BTC_NODE,
|
||||
"datadir": btcdatadir,
|
||||
"bindir": cfg.BITCOIN_BINDIR,
|
||||
"use_segwit": True,
|
||||
},
|
||||
},
|
||||
"check_progress_seconds": 2,
|
||||
"check_watched_seconds": 4,
|
||||
"check_expired_seconds": 60,
|
||||
"restrict_unknown_seed_wallets": False,
|
||||
}
|
||||
with open(settings_path, "w") as fp:
|
||||
json.dump(settings, fp, indent=4)
|
||||
fp.write("addnode=127.0.0.1:{}\n".format(NMC_BASE_PORT + i))
|
||||
|
||||
|
||||
def partRpc(cmd, node_id=0):
|
||||
return callrpc_cli(
|
||||
cfg.PARTICL_BINDIR,
|
||||
os.path.join(cfg.TEST_DATADIRS, str(node_id)),
|
||||
"regtest",
|
||||
cmd,
|
||||
cfg.PARTICL_CLI,
|
||||
)
|
||||
class TestNMC(BasicSwapTest):
|
||||
__test__ = True
|
||||
test_coin = Coins.NMC
|
||||
test_coin_from = Coins.NMC
|
||||
nmc_daemons = []
|
||||
start_ltc_nodes = False
|
||||
start_xmr_nodes = True
|
||||
base_rpc_port = NMC_BASE_RPC_PORT
|
||||
nmc_addr = None
|
||||
max_fee: int = 200000
|
||||
test_fee_rate: int = 100000 # sats/kvB
|
||||
|
||||
|
||||
def btcRpc(cmd):
|
||||
return callrpc_cli(
|
||||
cfg.BITCOIN_BINDIR,
|
||||
os.path.join(cfg.TEST_DATADIRS, str(BTC_NODE)),
|
||||
"regtest",
|
||||
cmd,
|
||||
cfg.BITCOIN_CLI,
|
||||
)
|
||||
|
||||
|
||||
def nmcRpc(cmd):
|
||||
return callrpc_cli(
|
||||
cfg.NAMECOIN_BINDIR,
|
||||
os.path.join(cfg.TEST_DATADIRS, str(NMC_NODE)),
|
||||
"regtest",
|
||||
cmd,
|
||||
cfg.NAMECOIN_CLI,
|
||||
)
|
||||
|
||||
|
||||
def signal_handler(sig, frame):
|
||||
global stop_test
|
||||
os.write(sys.stdout.fileno(), f"Signal {sig} detected.\n".encode("utf-8"))
|
||||
stop_test = True
|
||||
delay_event.set()
|
||||
|
||||
|
||||
def run_coins_loop(cls):
|
||||
while not stop_test:
|
||||
try:
|
||||
nmcRpc("generatetoaddress 1 {}".format(cls.nmc_addr))
|
||||
btcRpc("generatetoaddress 1 {}".format(cls.btc_addr))
|
||||
except Exception as e:
|
||||
logging.warning("run_coins_loop " + str(e))
|
||||
time.sleep(1.0)
|
||||
|
||||
|
||||
def run_loop(self):
|
||||
while not stop_test:
|
||||
for c in self.swap_clients:
|
||||
c.update()
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
def make_part_cli_rpc_func(node_id):
|
||||
node_id = node_id
|
||||
|
||||
def rpc_func(method, params=None, wallet=None):
|
||||
cmd = method
|
||||
if params:
|
||||
for p in params:
|
||||
cmd += ' "' + p + '"'
|
||||
return partRpc(cmd, node_id)
|
||||
|
||||
return rpc_func
|
||||
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(Test, cls).setUpClass()
|
||||
|
||||
eckey = ECKey()
|
||||
eckey.generate()
|
||||
cls.network_key = toWIF(PREFIX_SECRET_KEY_REGTEST, eckey.get_bytes())
|
||||
cls.network_pubkey = eckey.get_pubkey().get_bytes().hex()
|
||||
|
||||
if os.path.isdir(cfg.TEST_DATADIRS):
|
||||
logging.info("Removing " + cfg.TEST_DATADIRS)
|
||||
shutil.rmtree(cfg.TEST_DATADIRS)
|
||||
|
||||
for i in range(NUM_NODES):
|
||||
prepareDir(cfg.TEST_DATADIRS, i, cls.network_key, cls.network_pubkey)
|
||||
|
||||
prepareOtherDir(cfg.TEST_DATADIRS, NMC_NODE)
|
||||
prepareOtherDir(cfg.TEST_DATADIRS, BTC_NODE, "bitcoin.conf")
|
||||
|
||||
cls.daemons = []
|
||||
cls.swap_clients = []
|
||||
cls.http_threads = []
|
||||
|
||||
btc_data_dir = os.path.join(cfg.TEST_DATADIRS, str(BTC_NODE))
|
||||
if os.path.exists(os.path.join(cfg.BITCOIN_BINDIR, "bitcoin-wallet")):
|
||||
callrpc_cli(
|
||||
cfg.BITCOIN_BINDIR,
|
||||
btc_data_dir,
|
||||
"regtest",
|
||||
"-wallet=wallet.dat -legacy create",
|
||||
"bitcoin-wallet",
|
||||
)
|
||||
cls.daemons.append(startDaemon(btc_data_dir, cfg.BITCOIN_BINDIR, cfg.BITCOIND))
|
||||
logging.info("Started %s %d", cfg.BITCOIND, cls.daemons[-1].handle.pid)
|
||||
cls.daemons.append(
|
||||
startDaemon(
|
||||
os.path.join(cfg.TEST_DATADIRS, str(NMC_NODE)),
|
||||
cfg.NAMECOIN_BINDIR,
|
||||
cfg.NAMECOIND,
|
||||
)
|
||||
)
|
||||
logging.info("Started %s %d", cfg.NAMECOIND, cls.daemons[-1].handle.pid)
|
||||
|
||||
for i in range(NUM_NODES):
|
||||
data_dir = os.path.join(cfg.TEST_DATADIRS, str(i))
|
||||
if os.path.exists(os.path.join(cfg.PARTICL_BINDIR, "particl-wallet")):
|
||||
callrpc_cli(
|
||||
cfg.PARTICL_BINDIR,
|
||||
data_dir,
|
||||
"regtest",
|
||||
"-wallet=wallet.dat -legacy create",
|
||||
"particl-wallet",
|
||||
)
|
||||
cls.daemons.append(startDaemon(data_dir, cfg.PARTICL_BINDIR, cfg.PARTICLD))
|
||||
logging.info("Started %s %d", cfg.PARTICLD, cls.daemons[-1].handle.pid)
|
||||
|
||||
for i in range(NUM_NODES):
|
||||
rpc = make_part_cli_rpc_func(i)
|
||||
waitForRPC(rpc, delay_event)
|
||||
if i == 0:
|
||||
rpc(
|
||||
"extkeyimportmaster",
|
||||
[
|
||||
"abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb"
|
||||
],
|
||||
)
|
||||
elif i == 1:
|
||||
rpc(
|
||||
"extkeyimportmaster",
|
||||
[
|
||||
"pact mammal barrel matrix local final lecture chunk wasp survey bid various book strong spread fall ozone daring like topple door fatigue limb olympic",
|
||||
"",
|
||||
"true",
|
||||
],
|
||||
)
|
||||
rpc("getnewextaddress", ["lblExtTest"])
|
||||
rpc("rescanblockchain")
|
||||
else:
|
||||
rpc("extkeyimportmaster", [rpc("mnemonic", ["new"])["master"]])
|
||||
rpc(
|
||||
"walletsettings",
|
||||
[
|
||||
"stakingoptions",
|
||||
json.dumps(
|
||||
{"stakecombinethreshold": 100, "stakesplitthreshold": 200}
|
||||
).replace('"', '\\"'),
|
||||
],
|
||||
)
|
||||
rpc("reservebalance", ["false"])
|
||||
|
||||
basicswap_dir = os.path.join(
|
||||
os.path.join(cfg.TEST_DATADIRS, str(i)), "basicswap"
|
||||
)
|
||||
settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME)
|
||||
with open(settings_path) as fs:
|
||||
settings = json.load(fs)
|
||||
sc = BasicSwap(
|
||||
basicswap_dir, settings, "regtest", log_name="BasicSwap{}".format(i)
|
||||
)
|
||||
cls.swap_clients.append(sc)
|
||||
|
||||
sc.setDaemonPID(Coins.BTC, cls.daemons[0].handle.pid)
|
||||
sc.setDaemonPID(Coins.NMC, cls.daemons[1].handle.pid)
|
||||
sc.setDaemonPID(Coins.PART, cls.daemons[2 + i].handle.pid)
|
||||
sc.start()
|
||||
|
||||
t = HttpThread(TEST_HTTP_HOST, TEST_HTTP_PORT + i, False, sc)
|
||||
cls.http_threads.append(t)
|
||||
t.start()
|
||||
|
||||
waitForRPC(nmcRpc, delay_event)
|
||||
num_blocks = 500
|
||||
logging.info("Mining %d namecoin blocks", num_blocks)
|
||||
cls.nmc_addr = nmcRpc("getnewaddress mining_addr legacy")
|
||||
nmcRpc("generatetoaddress {} {}".format(num_blocks, cls.nmc_addr))
|
||||
|
||||
ro = nmcRpc("getblockchaininfo")
|
||||
try:
|
||||
assert ro["bip9_softforks"]["csv"]["status"] == "active"
|
||||
except Exception:
|
||||
logging.info("nmc: csv is not active")
|
||||
try:
|
||||
assert ro["bip9_softforks"]["segwit"]["status"] == "active"
|
||||
except Exception:
|
||||
logging.info("nmc: segwit is not active")
|
||||
|
||||
waitForRPC(btcRpc, delay_event)
|
||||
cls.btc_addr = btcRpc("getnewaddress mining_addr bech32")
|
||||
logging.info("Mining %d Bitcoin blocks to %s", num_blocks, cls.btc_addr)
|
||||
btcRpc("generatetoaddress {} {}".format(num_blocks, cls.btc_addr))
|
||||
|
||||
ro = btcRpc("getblockchaininfo")
|
||||
checkForks(ro)
|
||||
|
||||
ro = nmcRpc("getwalletinfo")
|
||||
print("nmcRpc", ro)
|
||||
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
cls.update_thread = threading.Thread(target=run_loop, args=(cls,))
|
||||
cls.update_thread.start()
|
||||
|
||||
cls.coins_update_thread = threading.Thread(target=run_coins_loop, args=(cls,))
|
||||
cls.coins_update_thread.start()
|
||||
|
||||
# Wait for height, or sequencelock is thrown off by genesis blocktime
|
||||
num_blocks = 3
|
||||
logging.info("Waiting for Particl chain height %d", num_blocks)
|
||||
for i in range(60):
|
||||
particl_blocks = cls.swap_clients[0].callrpc("getblockcount")
|
||||
print("particl_blocks", particl_blocks)
|
||||
if particl_blocks >= num_blocks:
|
||||
break
|
||||
delay_event.wait(1)
|
||||
assert particl_blocks >= num_blocks
|
||||
def mineBlock(self, num_blocks: int = 1) -> None:
|
||||
self.callnoderpc("generatetoaddress", [num_blocks, self.nmc_addr])
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
global stop_test
|
||||
logging.info("Finalising")
|
||||
stop_test = True
|
||||
cls.update_thread.join()
|
||||
cls.coins_update_thread.join()
|
||||
for t in cls.http_threads:
|
||||
t.stop()
|
||||
t.join()
|
||||
for c in cls.swap_clients:
|
||||
c.finalise()
|
||||
logging.info("Finalising Namecoin Test")
|
||||
stopDaemons(cls.nmc_daemons)
|
||||
cls.nmc_daemons.clear()
|
||||
|
||||
stopDaemons(cls.daemons)
|
||||
cls.http_threads.clear()
|
||||
cls.swap_clients.clear()
|
||||
cls.daemons.clear()
|
||||
super(TestNMC, cls).tearDownClass()
|
||||
|
||||
super(Test, cls).tearDownClass()
|
||||
|
||||
def test_02_part_nmc(self):
|
||||
logging.info("---------- Test PART to NMC")
|
||||
swap_clients = self.swap_clients
|
||||
|
||||
offer_id = swap_clients[0].postOffer(
|
||||
Coins.PART,
|
||||
Coins.NMC,
|
||||
100 * COIN,
|
||||
0.1 * COIN,
|
||||
100 * COIN,
|
||||
SwapTypes.SELLER_FIRST,
|
||||
TxLockTypes.ABS_LOCK_TIME,
|
||||
)
|
||||
|
||||
wait_for_offer(delay_event, swap_clients[1], offer_id)
|
||||
offer = swap_clients[1].getOffer(offer_id)
|
||||
bid_id = swap_clients[1].postBid(offer_id, offer.amount_from)
|
||||
|
||||
wait_for_bid(delay_event, swap_clients[0], bid_id)
|
||||
|
||||
swap_clients[0].acceptBid(bid_id)
|
||||
|
||||
wait_for_in_progress(delay_event, swap_clients[1], bid_id, sent=True)
|
||||
|
||||
wait_for_bid(
|
||||
delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60
|
||||
)
|
||||
wait_for_bid(
|
||||
delay_event,
|
||||
swap_clients[1],
|
||||
bid_id,
|
||||
BidStates.SWAP_COMPLETED,
|
||||
sent=True,
|
||||
wait_for=60,
|
||||
)
|
||||
|
||||
js_0 = read_json_api(1800)
|
||||
js_1 = read_json_api(1801)
|
||||
assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0
|
||||
assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0
|
||||
|
||||
def test_03_nmc_part(self):
|
||||
logging.info("---------- Test NMC to PART")
|
||||
swap_clients = self.swap_clients
|
||||
|
||||
offer_id = swap_clients[1].postOffer(
|
||||
Coins.NMC,
|
||||
Coins.PART,
|
||||
10 * COIN,
|
||||
9.0 * COIN,
|
||||
10 * COIN,
|
||||
SwapTypes.SELLER_FIRST,
|
||||
TxLockTypes.ABS_LOCK_TIME,
|
||||
)
|
||||
|
||||
wait_for_offer(delay_event, swap_clients[0], offer_id)
|
||||
offer = swap_clients[0].getOffer(offer_id)
|
||||
bid_id = swap_clients[0].postBid(offer_id, offer.amount_from)
|
||||
|
||||
wait_for_bid(delay_event, swap_clients[1], bid_id)
|
||||
swap_clients[1].acceptBid(bid_id)
|
||||
|
||||
wait_for_in_progress(delay_event, swap_clients[0], bid_id, sent=True)
|
||||
|
||||
wait_for_bid(
|
||||
delay_event,
|
||||
swap_clients[0],
|
||||
bid_id,
|
||||
BidStates.SWAP_COMPLETED,
|
||||
sent=True,
|
||||
wait_for=60,
|
||||
)
|
||||
wait_for_bid(
|
||||
delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, wait_for=60
|
||||
)
|
||||
|
||||
js_0 = read_json_api(1800)
|
||||
js_1 = read_json_api(1801)
|
||||
assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0
|
||||
assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0
|
||||
|
||||
def test_04_nmc_btc(self):
|
||||
logging.info("---------- Test NMC to BTC")
|
||||
swap_clients = self.swap_clients
|
||||
|
||||
offer_id = swap_clients[0].postOffer(
|
||||
Coins.NMC,
|
||||
Coins.BTC,
|
||||
10 * COIN,
|
||||
0.1 * COIN,
|
||||
10 * COIN,
|
||||
SwapTypes.SELLER_FIRST,
|
||||
TxLockTypes.ABS_LOCK_TIME,
|
||||
)
|
||||
|
||||
wait_for_offer(delay_event, swap_clients[1], offer_id)
|
||||
offer = swap_clients[1].getOffer(offer_id)
|
||||
bid_id = swap_clients[1].postBid(offer_id, offer.amount_from)
|
||||
|
||||
wait_for_bid(delay_event, swap_clients[0], bid_id)
|
||||
swap_clients[0].acceptBid(bid_id)
|
||||
|
||||
wait_for_in_progress(delay_event, swap_clients[1], bid_id, sent=True)
|
||||
|
||||
wait_for_bid(
|
||||
delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60
|
||||
)
|
||||
wait_for_bid(
|
||||
delay_event,
|
||||
swap_clients[1],
|
||||
bid_id,
|
||||
BidStates.SWAP_COMPLETED,
|
||||
sent=True,
|
||||
wait_for=60,
|
||||
)
|
||||
|
||||
js_0 = read_json_api(1800)
|
||||
js_1 = read_json_api(1801)
|
||||
|
||||
assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0
|
||||
assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0
|
||||
|
||||
def test_05_refund(self):
|
||||
# Seller submits initiate txn, buyer doesn't respond
|
||||
logging.info("---------- Test refund, NMC to BTC")
|
||||
swap_clients = self.swap_clients
|
||||
|
||||
offer_id = swap_clients[0].postOffer(
|
||||
Coins.NMC,
|
||||
Coins.BTC,
|
||||
10 * COIN,
|
||||
0.1 * COIN,
|
||||
10 * COIN,
|
||||
SwapTypes.SELLER_FIRST,
|
||||
TxLockTypes.ABS_LOCK_BLOCKS,
|
||||
10,
|
||||
)
|
||||
|
||||
wait_for_offer(delay_event, swap_clients[1], offer_id)
|
||||
offer = swap_clients[1].getOffer(offer_id)
|
||||
bid_id = swap_clients[1].postBid(offer_id, offer.amount_from)
|
||||
|
||||
wait_for_bid(delay_event, swap_clients[0], bid_id)
|
||||
swap_clients[1].abandonBid(bid_id)
|
||||
swap_clients[0].acceptBid(bid_id)
|
||||
|
||||
wait_for_bid(
|
||||
delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60
|
||||
)
|
||||
wait_for_bid(
|
||||
delay_event,
|
||||
swap_clients[1],
|
||||
bid_id,
|
||||
BidStates.BID_ABANDONED,
|
||||
sent=True,
|
||||
wait_for=60,
|
||||
)
|
||||
|
||||
js_0 = read_json_api(1800)
|
||||
js_1 = read_json_api(1801)
|
||||
assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0
|
||||
assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0
|
||||
|
||||
def test_06_self_bid(self):
|
||||
logging.info("---------- Test same client, BTC to NMC")
|
||||
swap_clients = self.swap_clients
|
||||
|
||||
js_0_before = read_json_api(1800)
|
||||
|
||||
offer_id = swap_clients[0].postOffer(
|
||||
Coins.NMC,
|
||||
Coins.BTC,
|
||||
10 * COIN,
|
||||
10 * COIN,
|
||||
10 * COIN,
|
||||
SwapTypes.SELLER_FIRST,
|
||||
TxLockTypes.ABS_LOCK_TIME,
|
||||
)
|
||||
|
||||
wait_for_offer(delay_event, swap_clients[0], offer_id)
|
||||
offer = swap_clients[0].getOffer(offer_id)
|
||||
bid_id = swap_clients[0].postBid(offer_id, offer.amount_from)
|
||||
|
||||
wait_for_bid(delay_event, swap_clients[0], bid_id)
|
||||
swap_clients[0].acceptBid(bid_id)
|
||||
|
||||
wait_for_bid_tx_state(
|
||||
delay_event,
|
||||
swap_clients[0],
|
||||
bid_id,
|
||||
TxStates.TX_REDEEMED,
|
||||
TxStates.TX_REDEEMED,
|
||||
wait_for=60,
|
||||
)
|
||||
wait_for_bid(
|
||||
delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60
|
||||
)
|
||||
|
||||
js_0 = read_json_api(1800)
|
||||
assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0
|
||||
assert (
|
||||
js_0["num_recv_bids"] == js_0_before["num_recv_bids"] + 1
|
||||
and js_0["num_sent_bids"] == js_0_before["num_sent_bids"] + 1
|
||||
)
|
||||
|
||||
def test_07_error(self):
|
||||
logging.info("---------- Test error, BTC to NMC, set fee above bid value")
|
||||
swap_clients = self.swap_clients
|
||||
|
||||
offer_id = swap_clients[0].postOffer(
|
||||
Coins.NMC,
|
||||
Coins.BTC,
|
||||
0.001 * COIN,
|
||||
1.0 * COIN,
|
||||
0.001 * COIN,
|
||||
SwapTypes.SELLER_FIRST,
|
||||
TxLockTypes.ABS_LOCK_TIME,
|
||||
)
|
||||
|
||||
wait_for_offer(delay_event, swap_clients[0], offer_id)
|
||||
offer = swap_clients[0].getOffer(offer_id)
|
||||
bid_id = swap_clients[0].postBid(offer_id, offer.amount_from)
|
||||
|
||||
wait_for_bid(delay_event, swap_clients[0], bid_id)
|
||||
swap_clients[0].acceptBid(bid_id)
|
||||
@classmethod
|
||||
def coins_loop(cls):
|
||||
super(TestNMC, cls).coins_loop()
|
||||
ci0 = cls.swap_clients[0].ci(cls.test_coin)
|
||||
try:
|
||||
swap_clients[0].getChainClientSettings(Coins.BTC)["override_feerate"] = 10.0
|
||||
swap_clients[0].getChainClientSettings(Coins.NMC)["override_feerate"] = 10.0
|
||||
wait_for_bid(
|
||||
delay_event, swap_clients[0], bid_id, BidStates.BID_ERROR, wait_for=60
|
||||
)
|
||||
swap_clients[0].abandonBid(bid_id)
|
||||
finally:
|
||||
del swap_clients[0].getChainClientSettings(Coins.BTC)["override_feerate"]
|
||||
del swap_clients[0].getChainClientSettings(Coins.NMC)["override_feerate"]
|
||||
if cls.nmc_addr is not None:
|
||||
ci0.rpc_wallet("generatetoaddress", [1, cls.nmc_addr])
|
||||
except Exception as e:
|
||||
logging.warning(f"coins_loop generate {e}")
|
||||
|
||||
def pass_99_delay(self):
|
||||
global stop_test
|
||||
logging.info("Delay")
|
||||
for i in range(60 * 5):
|
||||
if stop_test:
|
||||
break
|
||||
time.sleep(1)
|
||||
print("delay", i)
|
||||
stop_test = True
|
||||
@classmethod
|
||||
def prepareExtraDataDir(cls, i: int) -> None:
|
||||
if not cls.restore_instance:
|
||||
prepareNMCDataDir(cfg.TEST_DATADIRS, i)
|
||||
|
||||
cls.nmc_daemons.append(
|
||||
startDaemon(
|
||||
os.path.join(cfg.TEST_DATADIRS, "nmc_" + str(i)),
|
||||
NAMECOIN_BINDIR,
|
||||
NAMECOIND,
|
||||
)
|
||||
)
|
||||
logging.info("Started {} {}".format(NAMECOIND, cls.nmc_daemons[-1].handle.pid))
|
||||
|
||||
nmc_rpc = make_rpc_func(i, base_rpc_port=NMC_BASE_RPC_PORT)
|
||||
waitForRPC(
|
||||
nmc_rpc,
|
||||
test_delay_event,
|
||||
rpc_command="getnetworkinfo",
|
||||
max_tries=12,
|
||||
)
|
||||
waitForRPC(nmc_rpc, test_delay_event, rpc_command="getblockchaininfo")
|
||||
if len(nmc_rpc("listwallets")) < 1:
|
||||
nmc_rpc(
|
||||
"createwallet",
|
||||
["wallet.dat", False, True, "", False, NMC_USE_DESCRIPTORS],
|
||||
)
|
||||
if NMC_USE_DESCRIPTORS:
|
||||
nmc_rpc(
|
||||
"createwallet",
|
||||
["bsx_watch", True, True, "", False, True],
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def addPIDInfo(cls, sc, i):
|
||||
sc.setDaemonPID(Coins.DCR, cls.nmc_daemons[i].handle.pid)
|
||||
|
||||
@classmethod
|
||||
def addCoinSettings(cls, settings, datadir, node_id):
|
||||
settings["chainclients"]["namecoin"] = {
|
||||
"connection_type": "rpc",
|
||||
"manage_daemon": False,
|
||||
"rpcport": NMC_BASE_RPC_PORT + node_id,
|
||||
"rpcuser": "test" + str(node_id),
|
||||
"rpcpassword": "test_pass" + str(node_id),
|
||||
"datadir": os.path.join(datadir, "nmc_" + str(node_id)),
|
||||
"bindir": NAMECOIN_BINDIR,
|
||||
"use_csv": True,
|
||||
"use_segwit": True,
|
||||
"blocks_confirmed": 1,
|
||||
"use_descriptors": NMC_USE_DESCRIPTORS,
|
||||
}
|
||||
if NMC_USE_DESCRIPTORS:
|
||||
settings["chainclients"]["namecoin"]["watch_wallet_name"] = "bsx_watch"
|
||||
|
||||
@classmethod
|
||||
def prepareExtraCoins(cls):
|
||||
ci0 = cls.swap_clients[0].ci(cls.test_coin)
|
||||
if not cls.restore_instance:
|
||||
for sc in cls.swap_clients:
|
||||
ci = sc.ci(cls.test_coin)
|
||||
ci.initialiseWallet(ci.getNewRandomKey())
|
||||
cls.nmc_addr = ci0.rpc_wallet("getnewaddress", ["mining_addr", "bech32"])
|
||||
else:
|
||||
addrs = ci0.rpc_wallet(
|
||||
"getaddressesbylabel",
|
||||
[
|
||||
"mining_addr",
|
||||
],
|
||||
)
|
||||
cls.nmc_addr = addrs.keys()[0]
|
||||
|
||||
num_blocks: int = 500
|
||||
if ci0.rpc("getblockcount") < num_blocks:
|
||||
logging.info(f"Mining {num_blocks} Namecoin blocks to {cls.nmc_addr}")
|
||||
ci0.rpc("generatetoaddress", [num_blocks, cls.nmc_addr])
|
||||
logging.info("NMC blocks: {}".format(ci0.rpc("getblockcount")))
|
||||
|
||||
def test_007_hdwallet(self):
|
||||
logging.info("---------- Test {} hdwallet".format(self.test_coin_from.name))
|
||||
|
||||
test_seed = "8e54a313e6df8918df6d758fafdbf127a115175fdd2238d0e908dd8093c9ac3b"
|
||||
test_wif = (
|
||||
self.swap_clients[0]
|
||||
.ci(self.test_coin_from)
|
||||
.encodeKey(bytes.fromhex(test_seed))
|
||||
)
|
||||
new_wallet_name = random.randbytes(10).hex()
|
||||
self.callnoderpc(
|
||||
"createwallet",
|
||||
[new_wallet_name, False, False, "", False, NMC_USE_DESCRIPTORS],
|
||||
)
|
||||
self.callnoderpc("sethdseed", [True, test_wif], wallet=new_wallet_name)
|
||||
addr = self.callnoderpc(
|
||||
"getnewaddress", ["add test", "bech32"], wallet=new_wallet_name
|
||||
)
|
||||
self.callnoderpc("unloadwallet", [new_wallet_name])
|
||||
assert addr == "ncrt1qps7hnjd866e9ynxadgseprkc2l56m00dxkl7pk"
|
||||
|
||||
def test_012_p2sh_p2wsh(self):
|
||||
# Fee rate
|
||||
pass
|
||||
|
||||
def test_02_sh_part_coin(self):
|
||||
self.prepare_balance(self.test_coin, 200.0, 1801, 1800)
|
||||
run_test_success_path(self, Coins.PART, self.test_coin)
|
||||
|
||||
def test_03_sh_coin_part(self):
|
||||
run_test_success_path(self, self.test_coin, Coins.PART)
|
||||
|
||||
def test_04_sh_part_coin_bad_ptx(self):
|
||||
self.prepare_balance(self.test_coin, 200.0, 1801, 1800)
|
||||
run_test_bad_ptx(self, Coins.PART, self.test_coin)
|
||||
|
||||
def test_05_sh_coin_part_bad_ptx(self):
|
||||
self.prepare_balance(self.test_coin, 200.0, 1801, 1800)
|
||||
run_test_bad_ptx(self, self.test_coin, Coins.PART)
|
||||
|
||||
def test_06_sh_part_coin_itx_refund(self):
|
||||
run_test_itx_refund(self, Coins.PART, self.test_coin)
|
||||
|
||||
def test_07_sh_coin_part_itx_refund(self):
|
||||
self.prepare_balance(self.test_coin, 200.0, 1801, 1800)
|
||||
run_test_itx_refund(self, self.test_coin, Coins.PART)
|
||||
|
||||
def test_01_b_full_swap_reverse(self):
|
||||
self.prepare_balance(self.test_coin, 100.0, 1801, 1800)
|
||||
self.do_test_01_full_swap(Coins.XMR, self.test_coin_from)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
@ -60,6 +60,7 @@ from tests.basicswap.common_xmr import (
|
|||
prepare_nodes,
|
||||
XMR_BASE_RPC_PORT,
|
||||
DOGE_BASE_RPC_PORT,
|
||||
NMC_BASE_RPC_PORT,
|
||||
)
|
||||
from basicswap.interface.dcr.rpc import callrpc as callrpc_dcr
|
||||
import basicswap.bin.run as runSystem
|
||||
|
@ -73,12 +74,13 @@ UI_PORT = 12700 + PORT_OFS
|
|||
PARTICL_RPC_PORT_BASE = int(os.getenv("PARTICL_RPC_PORT_BASE", BASE_RPC_PORT))
|
||||
BITCOIN_RPC_PORT_BASE = int(os.getenv("BITCOIN_RPC_PORT_BASE", BTC_BASE_RPC_PORT))
|
||||
LITECOIN_RPC_PORT_BASE = int(os.getenv("LITECOIN_RPC_PORT_BASE", LTC_BASE_RPC_PORT))
|
||||
DOGECOIN_RPC_PORT_BASE = int(os.getenv("DOGECOIN_RPC_PORT_BASE", DOGE_BASE_RPC_PORT))
|
||||
DECRED_WALLET_RPC_PORT_BASE = int(os.getenv("DECRED_WALLET_RPC_PORT_BASE", 9210))
|
||||
NAMECOIN_RPC_PORT_BASE = int(os.getenv("NAMECOIN_RPC_PORT_BASE", NMC_BASE_RPC_PORT))
|
||||
XMR_BASE_RPC_PORT = int(os.getenv("XMR_BASE_RPC_PORT", XMR_BASE_RPC_PORT))
|
||||
BITCOINCASH_RPC_PORT_BASE = int(
|
||||
os.getenv("BITCOINCASH_RPC_PORT_BASE", BCH_BASE_RPC_PORT)
|
||||
)
|
||||
DECRED_WALLET_RPC_PORT_BASE = int(os.getenv("DECRED_WALLET_RPC_PORT_BASE", 9210))
|
||||
XMR_BASE_RPC_PORT = int(os.getenv("XMR_BASE_RPC_PORT", XMR_BASE_RPC_PORT))
|
||||
DOGECOIN_RPC_PORT_BASE = int(os.getenv("DOGECOIN_RPC_PORT_BASE", DOGE_BASE_RPC_PORT))
|
||||
TEST_COINS_LIST = os.getenv("TEST_COINS_LIST", "bitcoin,monero")
|
||||
|
||||
NUM_NODES = int(os.getenv("NUM_NODES", 3))
|
||||
|
@ -130,6 +132,17 @@ def calldcrrpc(
|
|||
return callrpc_dcr(base_rpc_port + node_id, auth, method, params)
|
||||
|
||||
|
||||
def callnmcrpc(
|
||||
node_id,
|
||||
method,
|
||||
params=[],
|
||||
wallet="wallet.dat",
|
||||
base_rpc_port=NAMECOIN_RPC_PORT_BASE + PORT_OFS,
|
||||
):
|
||||
auth = "test_nmc_{0}:test_nmc_pwd_{0}".format(node_id)
|
||||
return callrpc(base_rpc_port + node_id, auth, method, params, wallet)
|
||||
|
||||
|
||||
def callbchrpc(
|
||||
node_id,
|
||||
method,
|
||||
|
@ -163,6 +176,8 @@ def updateThread(cls):
|
|||
callbchrpc(0, "generatetoaddress", [1, cls.bch_addr])
|
||||
if cls.doge_addr is not None:
|
||||
calldogerpc(0, "generatetoaddress", [1, cls.doge_addr])
|
||||
if cls.nmc_addr is not None:
|
||||
callnmcrpc(0, "generatetoaddress", [1, cls.nmc_addr])
|
||||
except Exception as e:
|
||||
print("updateThread error", str(e))
|
||||
cls.delay_event.wait(random.randrange(cls.update_min, cls.update_max))
|
||||
|
@ -388,6 +403,18 @@ def start_processes(self):
|
|||
0, "generatetoaddress", [num_blocks - have_blocks, self.doge_addr]
|
||||
)
|
||||
|
||||
if "namecoin" in TEST_COINS_LIST:
|
||||
self.nmc_addr = callnmcrpc(0, "getnewaddress", ["mining_addr", "bech32"])
|
||||
num_blocks: int = 500
|
||||
have_blocks: int = callnmcrpc(0, "getblockcount")
|
||||
if have_blocks < num_blocks:
|
||||
logging.info(
|
||||
f"Mining {num_blocks - have_blocks} Namecoin blocks to {self.nmc_addr}"
|
||||
)
|
||||
callnmcrpc(
|
||||
0, "generatetoaddress", [num_blocks - have_blocks, self.nmc_addr]
|
||||
)
|
||||
|
||||
if RESET_TEST:
|
||||
# Lower output split threshold for more stakeable outputs
|
||||
for i in range(NUM_NODES):
|
||||
|
@ -444,6 +471,7 @@ class BaseTestWithPrepare(unittest.TestCase):
|
|||
dcr_addr = "SsYbXyjkKAEXXcGdFgr4u4bo4L8RkCxwQpH"
|
||||
dcr_acc = None
|
||||
doge_addr = None
|
||||
nmc_addr = None
|
||||
|
||||
initialised = False
|
||||
|
||||
|
|
|
@ -26,6 +26,9 @@ from basicswap.db import (
|
|||
from basicswap.util import (
|
||||
make_int,
|
||||
)
|
||||
from basicswap.util.address import (
|
||||
decodeAddress,
|
||||
)
|
||||
from basicswap.util.extkey import ExtKeyPair
|
||||
from basicswap.interface.base import Curves
|
||||
from tests.basicswap.util import (
|
||||
|
@ -59,7 +62,6 @@ from basicswap.contrib.test_framework.script import (
|
|||
from .test_xmr import BaseTest, test_delay_event, callnoderpc
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
test_seed = "8e54a313e6df8918df6d758fafdbf127a115175fdd2238d0e908dd8093c9ac3b"
|
||||
|
||||
|
||||
|
@ -183,7 +185,7 @@ class TestFunctions(BaseTest):
|
|||
bid0 = read_json_api(1800 + id_offerer, f"bids/{bid_id.hex()}")
|
||||
bid1 = read_json_api(1800 + id_bidder, f"bids/{bid_id.hex()}")
|
||||
|
||||
tolerance = 1
|
||||
tolerance = 2
|
||||
assert bid0["ticker_from"] == ci_from.ticker()
|
||||
assert bid1["ticker_from"] == ci_from.ticker()
|
||||
assert bid0["ticker_to"] == ci_to.ticker()
|
||||
|
@ -666,7 +668,7 @@ class TestFunctions(BaseTest):
|
|||
balance_from_before: float = self.getBalance(jsw, coin_from)
|
||||
self.prepare_balance(
|
||||
coin_to,
|
||||
balance_from_before + 1,
|
||||
balance_from_before * 3,
|
||||
1800 + id_bidder,
|
||||
1801 if coin_to in (Coins.XMR,) else 1800,
|
||||
)
|
||||
|
@ -718,6 +720,7 @@ class TestFunctions(BaseTest):
|
|||
assert False, "Should fail"
|
||||
|
||||
amt_swap -= ci_from.make_int(1)
|
||||
rate_swap = ci_to.make_int(1.0, r=1)
|
||||
offer_id = swap_clients[id_offerer].postOffer(
|
||||
coin_from,
|
||||
coin_to,
|
||||
|
@ -770,6 +773,8 @@ class TestFunctions(BaseTest):
|
|||
|
||||
class BasicSwapTest(TestFunctions):
|
||||
|
||||
test_fee_rate: int = 1000 # sats/kvB
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(BasicSwapTest, cls).setUpClass()
|
||||
|
@ -1178,6 +1183,10 @@ class BasicSwapTest(TestFunctions):
|
|||
logging.info("---------- Test {} hdwallet".format(self.test_coin_from.name))
|
||||
ci = self.swap_clients[0].ci(self.test_coin_from)
|
||||
|
||||
if hasattr(ci, "_use_descriptors") and ci._use_descriptors:
|
||||
logging.warning("Skipping test")
|
||||
return
|
||||
|
||||
test_wif = (
|
||||
self.swap_clients[0]
|
||||
.ci(self.test_coin_from)
|
||||
|
@ -1236,12 +1245,7 @@ class BasicSwapTest(TestFunctions):
|
|||
swap_client = self.swap_clients[0]
|
||||
ci = swap_client.ci(self.test_coin_from)
|
||||
|
||||
addr_1 = ci.rpc_wallet(
|
||||
"getnewaddress",
|
||||
[
|
||||
"gettxout test 1",
|
||||
],
|
||||
)
|
||||
addr_1 = ci.getNewAddress(True, "gettxout test 1")
|
||||
txid = ci.rpc_wallet("sendtoaddress", [addr_1, 1.0])
|
||||
assert len(txid) == 64
|
||||
|
||||
|
@ -1266,12 +1270,7 @@ class BasicSwapTest(TestFunctions):
|
|||
else:
|
||||
assert addr_1 in txout["scriptPubKey"]["addresses"]
|
||||
# Spend
|
||||
addr_2 = ci.rpc_wallet(
|
||||
"getnewaddress",
|
||||
[
|
||||
"gettxout test 2",
|
||||
],
|
||||
)
|
||||
addr_2 = ci.getNewAddress(True, "gettxout test 2")
|
||||
tx_funded = ci.rpc(
|
||||
"createrawtransaction",
|
||||
[[{"txid": utxo["txid"], "vout": utxo["vout"]}], {addr_2: 0.99}],
|
||||
|
@ -1297,12 +1296,7 @@ class BasicSwapTest(TestFunctions):
|
|||
logging.info("---------- Test {} scantxoutset".format(self.test_coin_from.name))
|
||||
ci = self.swap_clients[0].ci(self.test_coin_from)
|
||||
|
||||
addr_1 = ci.rpc_wallet(
|
||||
"getnewaddress",
|
||||
[
|
||||
"scantxoutset test",
|
||||
],
|
||||
)
|
||||
addr_1 = ci.getNewAddress(True, "scantxoutset test")
|
||||
txid = ci.rpc_wallet("sendtoaddress", [addr_1, 1.0])
|
||||
assert len(txid) == 64
|
||||
|
||||
|
@ -1323,10 +1317,7 @@ class BasicSwapTest(TestFunctions):
|
|||
|
||||
# Record unspents before createSCLockTx as the used ones will be locked
|
||||
unspents = ci.rpc_wallet("listunspent")
|
||||
|
||||
# fee_rate is in sats/kvB
|
||||
fee_rate: int = 1000
|
||||
|
||||
lockedunspents_before = ci.rpc_wallet("listlockunspent")
|
||||
a = ci.getNewRandomKey()
|
||||
b = ci.getNewRandomKey()
|
||||
|
||||
|
@ -1335,17 +1326,26 @@ class BasicSwapTest(TestFunctions):
|
|||
lock_tx_script = pi.genScriptLockTxScript(ci, A, B)
|
||||
|
||||
lock_tx = ci.createSCLockTx(amount, lock_tx_script)
|
||||
lock_tx = ci.fundSCLockTx(lock_tx, fee_rate)
|
||||
lock_tx = ci.fundSCLockTx(lock_tx, self.test_fee_rate)
|
||||
lock_tx = ci.signTxWithWallet(lock_tx)
|
||||
|
||||
# Check that inputs were locked
|
||||
lockedunspents = ci.rpc_wallet("listlockunspent")
|
||||
assert len(lockedunspents) > len(lockedunspents_before)
|
||||
unspents_after = ci.rpc_wallet("listunspent")
|
||||
assert len(unspents) > len(unspents_after)
|
||||
for utxo in unspents_after:
|
||||
for locked_utxo in lockedunspents:
|
||||
if (
|
||||
locked_utxo["txid"] == utxo["txid"]
|
||||
and locked_utxo["vout"] == utxo["vout"]
|
||||
):
|
||||
raise ValueError("Locked utxo in listunspent")
|
||||
|
||||
tx_decoded = ci.rpc("decoderawtransaction", [lock_tx.hex()])
|
||||
txid = tx_decoded["txid"]
|
||||
|
||||
vsize = tx_decoded["vsize"]
|
||||
expect_fee_int = round(fee_rate * vsize / 1000)
|
||||
expect_fee_int = round(self.test_fee_rate * vsize / 1000)
|
||||
|
||||
out_value: int = 0
|
||||
for txo in tx_decoded["vout"]:
|
||||
|
@ -1372,7 +1372,7 @@ class BasicSwapTest(TestFunctions):
|
|||
pkh_out = ci.decodeAddress(addr_out)
|
||||
fee_info = {}
|
||||
lock_spend_tx = ci.createSCLockSpendTx(
|
||||
lock_tx, lock_tx_script, pkh_out, fee_rate, fee_info=fee_info
|
||||
lock_tx, lock_tx_script, pkh_out, self.test_fee_rate, fee_info=fee_info
|
||||
)
|
||||
vsize_estimated: int = fee_info["vsize"]
|
||||
|
||||
|
@ -1400,11 +1400,11 @@ class BasicSwapTest(TestFunctions):
|
|||
v = ci.getNewRandomKey()
|
||||
s = ci.getNewRandomKey()
|
||||
S = ci.getPubkey(s)
|
||||
lock_tx_b_txid = ci.publishBLockTx(v, S, amount, fee_rate)
|
||||
lock_tx_b_txid = ci.publishBLockTx(v, S, amount, self.test_fee_rate)
|
||||
|
||||
addr_out = ci.getNewAddress(True)
|
||||
lock_tx_b_spend_txid = ci.spendBLockTx(
|
||||
lock_tx_b_txid, addr_out, v, s, amount, fee_rate, 0
|
||||
lock_tx_b_txid, addr_out, v, s, amount, self.test_fee_rate, 0
|
||||
)
|
||||
lock_tx_b_spend = ci.getTransaction(lock_tx_b_spend_txid)
|
||||
if lock_tx_b_spend is None:
|
||||
|
@ -1635,7 +1635,9 @@ class BasicSwapTest(TestFunctions):
|
|||
wallet=new_wallet_name,
|
||||
)
|
||||
|
||||
addr = self.callnoderpc("getnewaddress", wallet=new_wallet_name)
|
||||
addr = self.callnoderpc(
|
||||
"getnewaddress", ["test descriptors"], wallet=new_wallet_name
|
||||
)
|
||||
addr_info = self.callnoderpc(
|
||||
"getaddressinfo",
|
||||
[
|
||||
|
@ -1645,7 +1647,8 @@ class BasicSwapTest(TestFunctions):
|
|||
)
|
||||
assert addr_info["hdmasterfingerprint"] == "a55b7ea9"
|
||||
assert addr_info["hdkeypath"] == "m/0h/0h/0h"
|
||||
assert addr == "bcrt1qps7hnjd866e9ynxadgseprkc2l56m00dvwargr"
|
||||
if self.test_coin_from == Coins.BTC:
|
||||
assert addr == "bcrt1qps7hnjd866e9ynxadgseprkc2l56m00dvwargr"
|
||||
|
||||
addr_change = self.callnoderpc("getrawchangeaddress", wallet=new_wallet_name)
|
||||
addr_info = self.callnoderpc(
|
||||
|
@ -1657,7 +1660,8 @@ class BasicSwapTest(TestFunctions):
|
|||
)
|
||||
assert addr_info["hdmasterfingerprint"] == "a55b7ea9"
|
||||
assert addr_info["hdkeypath"] == "m/0h/1h/0h"
|
||||
assert addr_change == "bcrt1qdl9ryxkqjltv42lhfnqgdjf9tagxsjpp2xak9a"
|
||||
if self.test_coin_from == Coins.BTC:
|
||||
assert addr_change == "bcrt1qdl9ryxkqjltv42lhfnqgdjf9tagxsjpp2xak9a"
|
||||
|
||||
desc_watch = descsum_create(f"addr({addr})")
|
||||
self.callnoderpc(
|
||||
|
@ -1683,7 +1687,56 @@ class BasicSwapTest(TestFunctions):
|
|||
|
||||
# Test that addresses can be generated beyond range in listdescriptors
|
||||
for i in range(2000):
|
||||
self.callnoderpc("getnewaddress", wallet=new_wallet_name)
|
||||
self.callnoderpc(
|
||||
"getnewaddress",
|
||||
[
|
||||
f"t{i}",
|
||||
],
|
||||
wallet=new_wallet_name,
|
||||
)
|
||||
|
||||
# https://github.com/bitcoin/bitcoin/issues/10542
|
||||
# https://github.com/bitcoin/bitcoin/issues/26046
|
||||
sign_for_address: str = self.callnoderpc(
|
||||
"getnewaddress",
|
||||
[
|
||||
"sign address",
|
||||
],
|
||||
wallet=new_wallet_name,
|
||||
)
|
||||
priv_keys = self.callnoderpc("listdescriptors", [True], wallet=new_wallet_name)
|
||||
addr_info = self.callnoderpc(
|
||||
"getaddressinfo", [sign_for_address], wallet=new_wallet_name
|
||||
)
|
||||
hdkeypath = addr_info["hdkeypath"]
|
||||
|
||||
sign_for_address_key = None
|
||||
for descriptor in priv_keys["descriptors"]:
|
||||
if descriptor["active"] is False or descriptor["internal"] is True:
|
||||
continue
|
||||
desc = descriptor["desc"]
|
||||
assert desc.startswith("wpkh(")
|
||||
ext_key = desc[5:].split(")")[0].split("/", 1)[0]
|
||||
ext_key_data = decodeAddress(ext_key)[4:]
|
||||
ci_part = self.swap_clients[0].ci(Coins.PART)
|
||||
ext_key_data_part = ci_part.encode_secret_extkey(ext_key_data)
|
||||
rv = ci_part.rpc_wallet("extkey", ["info", ext_key_data_part, hdkeypath])
|
||||
extkey_derived = rv["key_info"]["result"]
|
||||
ext_key_data = decodeAddress(extkey_derived)[4:]
|
||||
ek = ExtKeyPair()
|
||||
ek.decode(ext_key_data)
|
||||
addr = ci.encodeSegwitAddress(ci.getAddressHashFromKey(ek._key))
|
||||
assert addr == sign_for_address
|
||||
sign_for_address_key = ci.encodeKey(ek._key)
|
||||
break
|
||||
assert sign_for_address_key is not None
|
||||
sign_message: str = "Would be better if dumpprivkey or signmessage worked"
|
||||
sig = self.callnoderpc(
|
||||
"signmessagewithprivkey",
|
||||
[sign_for_address_key, sign_message],
|
||||
wallet=new_wallet_name,
|
||||
)
|
||||
assert ci.verifyMessage(sign_for_address, sign_message, sig)
|
||||
|
||||
self.callnoderpc("unloadwallet", [new_wallet_name])
|
||||
self.callnoderpc("unloadwallet", [new_watch_wallet_name])
|
||||
|
|
Loading…
Reference in a new issue