diff --git a/lbry/lbry/conf.py b/lbry/lbry/conf.py index 916d57807..e779e1e43 100644 --- a/lbry/lbry/conf.py +++ b/lbry/lbry/conf.py @@ -9,6 +9,7 @@ from contextlib import contextmanager from appdirs import user_data_dir, user_config_dir from lbry.error import InvalidCurrencyError from lbry.dht import constants +from torba.client.coinselection import STRATEGIES log = logging.getLogger(__name__) @@ -192,6 +193,21 @@ class MaxKeyFee(Setting[dict]): ) +class OneOfString(String): + def __init__(self, valid_values: typing.List[str], *args, **kwargs): + super().__init__(*args, **kwargs) + self.valid_values = valid_values + if not self.valid_values: + raise ValueError(f"No valid values provided") + if self.default not in self.valid_values: + raise ValueError(f"Default value must be one of: " + ', '.join(self.valid_values)) + + def validate(self, val): + super().validate(val) + if val not in self.valid_values: + raise ValueError(f"Setting '{self.name}' must be one of: " + ', '.join(self.valid_values)) + + class ListSetting(Setting[list]): def validate(self, val): @@ -562,6 +578,9 @@ class Config(CLIConfig): streaming_get = Toggle("Enable the /get endpoint for the streaming media server. " "Disable to prevent new streams from being added.", True) + coin_selection_strategy = OneOfString(STRATEGIES, "Strategy to use when selecting UTXOs for a transaction", + "branch_and_bound") + @property def streaming_host(self): return self.streaming_server.split(':')[0] diff --git a/lbry/lbry/wallet/manager.py b/lbry/lbry/wallet/manager.py index 593d5fb53..51831fb22 100644 --- a/lbry/lbry/wallet/manager.py +++ b/lbry/lbry/wallet/manager.py @@ -13,6 +13,7 @@ from lbry.wallet.account import BaseAccount from lbry.wallet.transaction import Transaction from lbry.wallet.database import WalletDatabase from lbry.wallet.dewies import dewies_to_lbc +from lbrynet.conf import Config log = logging.getLogger(__name__) @@ -122,7 +123,7 @@ class LbryWalletManager(BaseWalletManager): return receiving_addresses, change_addresses @classmethod - async def from_lbrynet_config(cls, settings): + async def from_lbrynet_config(cls, settings: Config): ledger_id = { 'lbrycrd_main': 'lbc_mainnet', @@ -149,6 +150,7 @@ class LbryWalletManager(BaseWalletManager): 'wallets': [wallet_file_path] }) ledger = manager.get_or_create_ledger(ledger_id) + ledger.coin_selection_strategy = settings.coin_selection_strategy if manager.default_account is None: log.info('Wallet at %s is empty, generating a default account.', wallet_file_path) manager.default_wallet.generate_account(ledger) diff --git a/lbry/tests/unit/test_conf.py b/lbry/tests/unit/test_conf.py index 7af158bc8..1d8bc290f 100644 --- a/lbry/tests/unit/test_conf.py +++ b/lbry/tests/unit/test_conf.py @@ -4,7 +4,7 @@ import types import tempfile import unittest import argparse -from lbry.conf import Config, BaseConfig, String, Integer, Toggle, Servers, Strings, NOT_SET +from lbry.conf import Config, BaseConfig, String, Integer, Toggle, Servers, Strings, OneOfString, NOT_SET from lbry.error import InvalidCurrencyError @@ -15,6 +15,7 @@ class TestConfig(BaseConfig): test_true_toggle = Toggle('toggle help', True) servers = Servers('servers help', [('localhost', 80)]) strings = Strings('cheese', ['string']) + one_of_string = OneOfString(["a", "b", "c"], "one of string", "a") class ConfigurationTests(unittest.TestCase): @@ -225,3 +226,32 @@ class ConfigurationTests(unittest.TestCase): args = parser.parse_args(['--max-key-fee', '1.0', 'BTC']) c = Config.create_from_arguments(args) self.assertEqual(c.max_key_fee, {'amount': 1.0, 'currency': 'BTC'}) + + def test_one_of_string(self): + with self.assertRaises(ValueError): + no_vaid_values = OneOfString([], "no valid values", None) + + with self.assertRaises(ValueError): + default_none = OneOfString(["a"], "invalid default", None) + with self.assertRaises(ValueError): + invalid_default = OneOfString(["a"], "invalid default", "b") + + valid_default = OneOfString(["a"], "valid default", "a") + + self.assertEqual("hello", OneOfString(["hello"], "valid default", "hello").default) + + c = TestConfig() + with self.assertRaises(ValueError): + c.one_of_string = "d" + + parser = argparse.ArgumentParser() + TestConfig.contribute_to_argparse(parser) + + args = parser.parse_args(["--one-of-string=b"]) + c = TestConfig.create_from_arguments(args) + self.assertEqual("b", c.one_of_string) + + # with self.assertRaises(ValueError): + # args = parser.parse_args(["--one-of-string=arst"]) + # c = TestConfig.create_from_arguments(args) + # print("here")