Fix: Clean BSX install litewallets switch in RPC mode wallet creation (RPC: BTC/LTC(+MWEB)

This commit is contained in:
gerlofvanek
2026-01-30 22:34:25 +01:00
parent e67e37b801
commit 1afe1316d0
3 changed files with 271 additions and 17 deletions

View File

@@ -1670,8 +1670,13 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
def checkSystemStatus(self) -> None:
ci = self.ci(Coins.PART)
if ci.isWalletLocked():
raise LockedCoinError(Coins.PART)
try:
if ci.isWalletLocked():
raise LockedCoinError(Coins.PART)
except Exception as e:
if "not exist or is not loaded" in str(e):
raise LockedCoinError(Coins.PART)
raise
def checkForUpdates(self) -> None:
if not self.settings.get("check_updates", True):
@@ -4501,10 +4506,7 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
return False
try:
wallet_seedid = ci.getWalletSeedID()
except Exception as e:
self.log.debug(
f"checkWalletSeed {ci.coin_name()}: getWalletSeedID failed: {e}"
)
except Exception:
wallet_seedid = None
if ci.checkExpectedSeed(expect_seedid):
ci.setWalletSeedWarning(False)

View File

@@ -378,7 +378,7 @@ class BTCInterface(Secp256k1Interface):
f"Wallet: {self._rpc_wallet} not active, attempting to load."
)
try:
self.rpc_wallet(
self.rpc(
"loadwallet",
[
self._rpc_wallet,
@@ -386,7 +386,31 @@ class BTCInterface(Secp256k1Interface):
)
wallets = self.rpc("listwallets")
except Exception as e:
self._log.debug(f'Error loading wallet "self._rpc_wallet": {e}.')
self._log.debug(f'Error loading wallet "{self._rpc_wallet}": {e}.')
if "does not exist" in str(e) or "Path does not exist" in str(e):
self._log.info(
f'Creating wallet "{self._rpc_wallet}" for {self.coin_name()}.'
)
try:
self.rpc(
"createwallet",
[
self._rpc_wallet,
False,
True,
"",
False,
self._use_descriptors,
],
)
wallets = self.rpc("listwallets")
if self.getWalletSeedID() == "Not found":
self._log.info(
f"Initializing HD seed for {self.coin_name()}."
)
self._sc.initialiseWallet(self.coin_type())
except Exception as create_e:
self._log.error(f"Error creating wallet: {create_e}")
# Wallet name is "" for some LTC and PART installs on older cores
if self._rpc_wallet not in wallets and len(wallets) > 0:
@@ -578,6 +602,7 @@ class BTCInterface(Secp256k1Interface):
self.rpc_wallet("sethdseed", [True, key_wif])
except Exception as e:
self._log.debug(f"sethdseed failed: {e}")
"""
# TODO: Find derived key counts
if "Already have this key" in str(e):
@@ -585,7 +610,11 @@ class BTCInterface(Secp256k1Interface):
self.setActiveKeyChain(key_id)
else:
"""
raise (e)
if "Already have this key" not in str(e):
raise (e)
self._log.info(
f"{self.coin_name()} wallet already has the correct HD seed."
)
def canExportToElectrum(self) -> bool:
# keychains must be unhardened to export into electrum
@@ -1869,6 +1898,7 @@ class BTCInterface(Secp256k1Interface):
final_vsize = (
10 + len(funded_tx.vout) * 34 + len(selected_utxos) * input_vsize
)
min_relay_fee = 250
final_fee = max(final_vsize * fee_per_vbyte, min_relay_fee)
change = 0 # Goes to fees
@@ -3952,7 +3982,7 @@ class BTCInterface(Secp256k1Interface):
# Recreate wallet if none found
# Required when encrypting an existing btc/ltc wallet, or switching from electrum to rpc mode. Workaround is to delete the btc/ltc wallet and recreate.
wallets = self.rpc("listwallets")
if len(wallets) < 1:
if self._rpc_wallet not in wallets:
self._log.info(
f'Creating wallet "{self._rpc_wallet}" for {self.coin_name()}.'
)
@@ -3969,8 +3999,43 @@ class BTCInterface(Secp256k1Interface):
],
)
# Max timeout value, ~3 years
self.rpc_wallet("walletpassphrase", [password, 100000000])
try:
seed_id = self.getWalletSeedID()
self._log.debug(
f"{self.ticker()} unlockWallet getWalletSeedID returned: {seed_id}"
)
needs_seed_init = seed_id == "Not found"
except Exception as e:
self._log.debug(f"getWalletSeedID failed: {e}, will initialize seed")
needs_seed_init = True
if needs_seed_init:
self._log.info(f"Initializing HD seed for {self.coin_name()}.")
self._sc.initialiseWallet(self.coin_type())
if password:
self._log.info(f"Encrypting {self.coin_name()} wallet.")
try:
self.rpc_wallet("encryptwallet", [password])
except Exception as e:
self._log.debug(f"encryptwallet returned: {e}")
import time
for i in range(10):
time.sleep(1)
try:
self.rpc("listwallets")
break
except Exception:
self._log.debug(
f"Waiting for wallet after encryption... {i+1}/10"
)
wallets = self.rpc("listwallets")
if self._rpc_wallet not in wallets:
self.rpc("loadwallet", [self._rpc_wallet])
self.setWalletSeedWarning(False)
check_seed = False
if self.isWalletEncrypted():
self.rpc_wallet("walletpassphrase", [password, 100000000])
if check_seed:
self._sc.checkWalletSeed(self.coin_type())

View File

@@ -26,6 +26,80 @@ class LTCInterface(BTCInterface):
wallet=self._rpc_wallet_mweb,
)
def checkWallets(self) -> int:
if self._connection_type == "electrum":
wm = self.getWalletManager()
if wm and wm.isInitialized(self.coin_type()):
return 1
return 0
wallets = self.rpc("listwallets")
if self._rpc_wallet not in wallets:
self._log.debug(
f"Wallet: {self._rpc_wallet} not active, attempting to load."
)
try:
self.rpc(
"loadwallet",
[
self._rpc_wallet,
],
)
wallets = self.rpc("listwallets")
except Exception as e:
self._log.debug(f'Error loading wallet "{self._rpc_wallet}": {e}.')
if "does not exist" in str(e) or "Path does not exist" in str(e):
self._log.info(
f'Creating wallet "{self._rpc_wallet}" for {self.coin_name()}.'
)
try:
self.rpc(
"createwallet",
[
self._rpc_wallet,
False,
True,
"",
False,
self._use_descriptors,
],
)
wallets = self.rpc("listwallets")
if self.getWalletSeedID() == "Not found":
self._log.info(
f"Initializing HD seed for {self.coin_name()}."
)
self._sc.initialiseWallet(self.coin_type())
except Exception as create_e:
self._log.error(f"Error creating wallet: {create_e}")
if self._rpc_wallet not in wallets and len(wallets) > 0:
self._log.warning(f"Changing {self.ticker()} wallet name.")
for wallet_name in wallets:
if wallet_name in ("mweb",):
continue
change_watchonly_wallet: bool = (
self._rpc_wallet_watch == self._rpc_wallet
)
self._rpc_wallet = wallet_name
self._log.info(
f"Switched {self.ticker()} wallet name to {self._rpc_wallet}."
)
self.rpc_wallet = make_rpc_func(
self._rpcport,
self._rpcauth,
host=self._rpc_host,
wallet=self._rpc_wallet,
)
if change_watchonly_wallet:
self.rpc_wallet_watch = self.rpc_wallet
break
return len(wallets)
def getNewMwebAddress(self, use_segwit=False, label="swap_receive") -> str:
if self.useBackend():
raise ValueError("MWEB addresses not supported in electrum mode")
@@ -108,6 +182,71 @@ class LTCInterface(BTCInterface):
) + self.make_int(u["amount"], r=1)
return unspent_addr
def unlockWallet(self, password: str, check_seed: bool = True) -> None:
if password == "":
return
self._log.info("unlockWallet - {}".format(self.ticker()))
if self.useBackend():
return
wallets = self.rpc("listwallets")
if self._rpc_wallet not in wallets:
self._log.info(
f'Creating wallet "{self._rpc_wallet}" for {self.coin_name()}.'
)
self.rpc(
"createwallet",
[
self._rpc_wallet,
False,
True,
password,
False,
self._use_descriptors,
],
)
try:
seed_id = self.getWalletSeedID()
self._log.debug(f"LTC unlockWallet getWalletSeedID returned: {seed_id}")
needs_seed_init = seed_id == "Not found"
except Exception as e:
self._log.debug(f"getWalletSeedID failed: {e}, will initialize seed")
needs_seed_init = True
if needs_seed_init:
self._log.info(f"Initializing HD seed for {self.coin_name()}.")
self._sc.initialiseWallet(self.coin_type())
if password:
self._log.info(f"Encrypting {self.coin_name()} wallet.")
try:
self.rpc_wallet("encryptwallet", [password])
except Exception as e:
self._log.debug(f"encryptwallet returned: {e}")
import time
for i in range(10):
time.sleep(1)
try:
self.rpc("listwallets")
break
except Exception:
self._log.debug(
f"Waiting for wallet after encryption... {i+1}/10"
)
wallets = self.rpc("listwallets")
if self._rpc_wallet not in wallets:
self.rpc("loadwallet", [self._rpc_wallet])
self.setWalletSeedWarning(False)
check_seed = False
if self.isWalletEncrypted():
self.rpc_wallet("walletpassphrase", [password, 100000000])
if check_seed:
self._sc.checkWalletSeed(self.coin_type())
class LTCInterfaceMWEB(LTCInterface):
@@ -151,9 +290,45 @@ class LTCInterfaceMWEB(LTCInterface):
self._log.info("init_wallet - {}".format(self.ticker()))
self._log.info(f"Creating wallet {self._rpc_wallet} for {self.coin_name()}.")
# wallet_name, disable_private_keys, blank, passphrase, avoid_reuse, descriptors, load_on_startup
self.rpc("createwallet", ["mweb", False, True, password, False, False, True])
wallets = self.rpc("listwallets")
if self._rpc_wallet not in wallets:
try:
self.rpc("loadwallet", [self._rpc_wallet])
self._log.debug(f'Loaded existing wallet "{self._rpc_wallet}".')
except Exception as e:
if "does not exist" in str(e) or "Path does not exist" in str(e):
self._log.info(
f'Creating wallet "{self._rpc_wallet}" for {self.coin_name()}.'
)
self.rpc(
"createwallet",
[
self._rpc_wallet,
False,
True,
password,
False,
self._use_descriptors,
],
)
else:
raise
wallets = self.rpc("listwallets")
if "mweb" not in wallets:
try:
self.rpc("loadwallet", ["mweb"])
self._log.debug("Loaded existing MWEB wallet.")
except Exception as e:
if "does not exist" in str(e) or "Path does not exist" in str(e):
self._log.info(f"Creating MWEB wallet for {self.coin_name()}.")
# wallet_name, disable_private_keys, blank, passphrase, avoid_reuse, descriptors, load_on_startup
self.rpc(
"createwallet",
["mweb", False, True, password, False, False, True],
)
else:
raise
if password is not None:
# Max timeout value, ~3 years
@@ -180,7 +355,19 @@ class LTCInterfaceMWEB(LTCInterface):
if not self.has_mweb_wallet():
self.init_wallet(password)
else:
# Max timeout value, ~3 years
self.rpc_wallet("walletpassphrase", [password, 100000000])
try:
seed_id = self.getWalletSeedID()
self._log.debug(
f"LTC_MWEB unlockWallet getWalletSeedID returned: {seed_id}"
)
needs_seed_init = seed_id == "Not found"
except Exception as e:
self._log.debug(f"getWalletSeedID failed: {e}, will initialize seed")
needs_seed_init = True
if needs_seed_init:
self._log.info(f"Initializing HD seed for {self.coin_name()}.")
self._sc.initialiseWallet(self.interface_type())
if check_seed:
self._sc.checkWalletSeed(self.coin_type())
self._sc.checkWalletSeed(self.interface_type())