mirror of
https://github.com/yzernik/squeaknode.git
synced 2026-08-13 12:33:25 +02:00
Implement node settings (#1884)
* Implement node settings class * Fix price policy for zero price * Remove old comment * Remove old comments * Remove old comments
This commit is contained in:
parent
d4a1843e30
commit
c2aeb344bc
7 changed files with 160 additions and 60 deletions
64
squeaknode/node/node_settings.py
Normal file
64
squeaknode/node/node_settings.py
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
# MIT License
|
||||
#
|
||||
# Copyright (c) 2020 Jonathan Zernik
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
import logging
|
||||
from typing import Optional
|
||||
|
||||
from squeaknode.core.user_config import UserConfig
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
NODE_SETTINGS_USERNAME = "default"
|
||||
|
||||
|
||||
class NodeSettings:
|
||||
|
||||
def __init__(self, squeak_db):
|
||||
self.squeak_db = squeak_db
|
||||
self.username = NODE_SETTINGS_USERNAME
|
||||
|
||||
def insert_user_config(self) -> Optional[str]:
|
||||
user_config = UserConfig(username=self.username)
|
||||
return self.squeak_db.insert_config(user_config)
|
||||
|
||||
def set_sell_price_msat(self, sell_price_msat: int) -> None:
|
||||
self.insert_user_config()
|
||||
if sell_price_msat < 0:
|
||||
raise Exception("Sell price cannot be negative.")
|
||||
self.squeak_db.set_config_sell_price_msat(
|
||||
username=self.username,
|
||||
sell_price_msat=sell_price_msat,
|
||||
)
|
||||
|
||||
def clear_sell_price_msat(self) -> None:
|
||||
self.insert_user_config()
|
||||
self.squeak_db.clear_config_sell_price_msat(
|
||||
username=self.username,
|
||||
)
|
||||
|
||||
def get_sell_price_msat(self) -> Optional[int]:
|
||||
user_config = self.squeak_db.get_config(
|
||||
username=self.username,
|
||||
)
|
||||
if user_config is None:
|
||||
return None
|
||||
return user_config.sell_price_msat
|
||||
|
|
@ -27,8 +27,8 @@ from squeak.core import CSqueak
|
|||
from squeaknode.config.config import SqueaknodeConfig
|
||||
from squeaknode.core.peer_address import PeerAddress
|
||||
from squeaknode.core.squeak_peer import SqueakPeer
|
||||
from squeaknode.core.user_config import UserConfig
|
||||
from squeaknode.db.squeak_db import SqueakDb
|
||||
from squeaknode.node.node_settings import NodeSettings
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
@ -36,9 +36,10 @@ logger = logging.getLogger(__name__)
|
|||
|
||||
class PricePolicy:
|
||||
|
||||
def __init__(self, squeak_db: SqueakDb, config: SqueaknodeConfig):
|
||||
def __init__(self, squeak_db: SqueakDb, config: SqueaknodeConfig, node_settings: NodeSettings):
|
||||
self.squeak_db = squeak_db
|
||||
self.config = config
|
||||
self.node_settings = node_settings
|
||||
|
||||
def get_price(self, squeak: CSqueak, peer_address: PeerAddress) -> int:
|
||||
"""Get the price to sell this squeak to this peer.
|
||||
|
|
@ -48,11 +49,10 @@ class PricePolicy:
|
|||
peer = self.get_peer(peer_address)
|
||||
if peer is not None and peer.share_for_free:
|
||||
return 0
|
||||
# Return sell price from settings if configured
|
||||
sell_price = self.get_sell_price_msat()
|
||||
if sell_price is not None:
|
||||
return sell_price
|
||||
return self.get_default_price()
|
||||
sell_price_msat = self.get_sell_price_msat()
|
||||
if sell_price_msat is None:
|
||||
return self.get_default_price()
|
||||
return sell_price_msat
|
||||
|
||||
def get_peer(self, peer_address: PeerAddress) -> Optional[SqueakPeer]:
|
||||
return self.squeak_db.get_peer_by_address(peer_address)
|
||||
|
|
@ -60,13 +60,5 @@ class PricePolicy:
|
|||
def get_default_price(self) -> int:
|
||||
return self.config.node.price_msat
|
||||
|
||||
def get_user_config(self) -> Optional[UserConfig]:
|
||||
return self.squeak_db.get_config(
|
||||
username=self.config.webadmin.username,
|
||||
)
|
||||
|
||||
def get_sell_price_msat(self) -> Optional[int]:
|
||||
user_config = self.get_user_config()
|
||||
if user_config is None:
|
||||
return None
|
||||
return user_config.sell_price_msat
|
||||
return self.node_settings.get_sell_price_msat()
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ class SqueakController:
|
|||
network_manager,
|
||||
download_manager,
|
||||
tweet_forwarder,
|
||||
node_settings,
|
||||
config,
|
||||
):
|
||||
self.squeak_db = squeak_db
|
||||
|
|
@ -100,6 +101,7 @@ class SqueakController:
|
|||
self.twitter_stream_change_listener = EventListener()
|
||||
self.active_download_manager = download_manager
|
||||
self.tweet_forwarder = tweet_forwarder
|
||||
self.node_settings = node_settings
|
||||
self.config = config
|
||||
|
||||
def save_squeak(self, squeak: CSqueak) -> Optional[bytes]:
|
||||
|
|
@ -253,7 +255,8 @@ class SqueakController:
|
|||
return sent_offer
|
||||
|
||||
def get_price_for_squeak(self, squeak: CSqueak, peer_address: PeerAddress) -> int:
|
||||
price_policy = PricePolicy(self.squeak_db, self.config)
|
||||
price_policy = PricePolicy(
|
||||
self.squeak_db, self.config, self.node_settings)
|
||||
return price_policy.get_price(squeak, peer_address)
|
||||
|
||||
def create_signing_profile(self, profile_name: str) -> int:
|
||||
|
|
@ -868,27 +871,13 @@ class SqueakController:
|
|||
return self.squeak_db.insert_config(user_config)
|
||||
|
||||
def set_sell_price_msat(self, sell_price_msat: int) -> None:
|
||||
self.insert_user_config()
|
||||
if sell_price_msat < 0:
|
||||
raise Exception("Sell price cannot be negative.")
|
||||
self.squeak_db.set_config_sell_price_msat(
|
||||
username=self.config.webadmin.username,
|
||||
sell_price_msat=sell_price_msat,
|
||||
)
|
||||
self.node_settings.set_sell_price_msat(sell_price_msat)
|
||||
|
||||
def clear_sell_price_msat(self) -> None:
|
||||
self.insert_user_config()
|
||||
self.squeak_db.clear_config_sell_price_msat(
|
||||
username=self.config.webadmin.username,
|
||||
)
|
||||
self.node_settings.clear_sell_price_msat()
|
||||
|
||||
def get_sell_price_msat(self) -> Optional[int]:
|
||||
user_config = self.squeak_db.get_config(
|
||||
username=self.config.webadmin.username,
|
||||
)
|
||||
if user_config is None:
|
||||
return None
|
||||
return user_config.sell_price_msat
|
||||
return self.node_settings.get_sell_price_msat()
|
||||
|
||||
def get_default_sell_price_msat(self) -> int:
|
||||
return self.config.node.price_msat
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ from squeaknode.db.squeak_db import SqueakDb
|
|||
from squeaknode.lightning.lnd_lightning_client import LNDLightningClient
|
||||
from squeaknode.network.network_manager import NetworkManager
|
||||
from squeaknode.node.active_download_manager import ActiveDownloadManager
|
||||
from squeaknode.node.node_settings import NodeSettings
|
||||
from squeaknode.node.payment_processor import PaymentProcessor
|
||||
from squeaknode.node.peer_connection_worker import PeerConnectionWorker
|
||||
from squeaknode.node.peer_subscription_update_worker import PeerSubscriptionUpdateWorker
|
||||
|
|
@ -61,6 +62,7 @@ class SqueakNode:
|
|||
def _initialize(self):
|
||||
self.initialize_network()
|
||||
self.initialize_db()
|
||||
self.initialize_node_settings()
|
||||
self.initialize_lightning_client()
|
||||
self.initialize_bitcoin_client()
|
||||
self.initialize_bitcoin_block_subscription_client()
|
||||
|
|
@ -132,6 +134,9 @@ class SqueakNode:
|
|||
self.squeak_db = SqueakDb(engine)
|
||||
self.squeak_db.init_with_retries()
|
||||
|
||||
def initialize_node_settings(self):
|
||||
self.node_settings = NodeSettings(self.squeak_db)
|
||||
|
||||
def initialize_lightning_client(self):
|
||||
# load the lightning client
|
||||
self.lightning_client = LNDLightningClient(
|
||||
|
|
@ -188,6 +193,7 @@ class SqueakNode:
|
|||
self.network_manager,
|
||||
self.download_manager,
|
||||
self.twitter_forwarder,
|
||||
self.node_settings,
|
||||
self.config,
|
||||
)
|
||||
|
||||
|
|
|
|||
58
tests/node/test_node_settings.py
Normal file
58
tests/node/test_node_settings.py
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
# MIT License
|
||||
#
|
||||
# Copyright (c) 2020 Jonathan Zernik
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
import pytest
|
||||
from sqlalchemy import create_engine
|
||||
|
||||
from squeaknode.db.squeak_db import SqueakDb
|
||||
from squeaknode.node.node_settings import NodeSettings
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def db_engine():
|
||||
yield create_engine('sqlite://')
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def squeak_db(db_engine):
|
||||
db = SqueakDb(db_engine)
|
||||
db.init()
|
||||
yield db
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def node_settings(
|
||||
squeak_db,
|
||||
):
|
||||
return NodeSettings(squeak_db)
|
||||
|
||||
|
||||
def test_default_set_sell_price(node_settings):
|
||||
retrieved_sell_price_msat = node_settings.get_sell_price_msat()
|
||||
|
||||
assert retrieved_sell_price_msat is None
|
||||
|
||||
|
||||
def test_set_sell_price(node_settings):
|
||||
node_settings.set_sell_price_msat(666)
|
||||
retrieved_sell_price_msat = node_settings.get_sell_price_msat()
|
||||
|
||||
assert retrieved_sell_price_msat == 666
|
||||
|
|
@ -27,54 +27,35 @@ from squeaknode.node.price_policy import PricePolicy
|
|||
|
||||
@pytest.fixture()
|
||||
def price_policy():
|
||||
yield PricePolicy(None, None)
|
||||
yield PricePolicy(None, None, None)
|
||||
|
||||
|
||||
def test_get_price(price_policy, squeak, peer_address, user_config):
|
||||
with mock.patch.object(price_policy, 'get_peer', autospec=True) as mock_get_peer, \
|
||||
mock.patch.object(price_policy, 'get_user_config', autospec=True) as mock_get_user_config, \
|
||||
mock.patch.object(price_policy, 'get_default_price', autospec=True) as mock_get_default_price:
|
||||
mock.patch.object(price_policy, 'get_sell_price_msat', autospec=True) as mock_get_sell_price_msat:
|
||||
mock_get_peer.return_value = None
|
||||
mock_get_user_config.return_value = user_config
|
||||
mock_get_default_price.return_value = 555
|
||||
mock_get_sell_price_msat.return_value = 555
|
||||
|
||||
assert price_policy.get_price(squeak, peer_address) == 555
|
||||
|
||||
|
||||
def test_get_price_profile_share_free_peer(price_policy, squeak, peer_address, peer, user_config):
|
||||
with mock.patch.object(price_policy, 'get_peer', autospec=True) as mock_get_peer, \
|
||||
mock.patch.object(price_policy, 'get_user_config', autospec=True) as mock_get_user_config, \
|
||||
mock.patch.object(price_policy, 'get_default_price', autospec=True) as mock_get_default_price:
|
||||
mock.patch.object(price_policy, 'get_sell_price_msat', autospec=True) as mock_get_sell_price_msat:
|
||||
mock_get_peer.return_value = peer._replace(
|
||||
share_for_free=True,
|
||||
)
|
||||
mock_get_user_config.return_value = user_config
|
||||
mock_get_default_price.return_value = 555
|
||||
mock_get_sell_price_msat.return_value = 555
|
||||
|
||||
assert price_policy.get_price(squeak, peer_address) == 0
|
||||
|
||||
|
||||
def test_get_price_profile_no_share_free_peer(price_policy, squeak, peer_address, peer, user_config):
|
||||
with mock.patch.object(price_policy, 'get_peer', autospec=True) as mock_get_peer, \
|
||||
mock.patch.object(price_policy, 'get_user_config', autospec=True) as mock_get_user_config, \
|
||||
mock.patch.object(price_policy, 'get_default_price', autospec=True) as mock_get_default_price:
|
||||
mock.patch.object(price_policy, 'get_sell_price_msat', autospec=True) as mock_get_sell_price_msat:
|
||||
mock_get_peer.return_value = peer._replace(
|
||||
share_for_free=False,
|
||||
)
|
||||
mock_get_user_config.return_value = user_config
|
||||
mock_get_default_price.return_value = 555
|
||||
mock_get_sell_price_msat.return_value = 555
|
||||
|
||||
assert price_policy.get_price(squeak, peer_address) == 555
|
||||
|
||||
|
||||
def test_get_price_sell_price_set(price_policy, squeak, peer_address, user_config):
|
||||
with mock.patch.object(price_policy, 'get_peer', autospec=True) as mock_get_peer, \
|
||||
mock.patch.object(price_policy, 'get_user_config', autospec=True) as mock_get_user_config, \
|
||||
mock.patch.object(price_policy, 'get_default_price', autospec=True) as mock_get_default_price:
|
||||
mock_get_peer.return_value = None
|
||||
mock_get_user_config.return_value = user_config._replace(
|
||||
sell_price_msat=7777,
|
||||
)
|
||||
mock_get_default_price.return_value = 555
|
||||
|
||||
assert price_policy.get_price(squeak, peer_address) == 7777
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ from squeaknode.core.squeak_peer import SqueakPeer
|
|||
from squeaknode.db.squeak_db import SqueakDb
|
||||
from squeaknode.network.network_manager import NetworkManager
|
||||
from squeaknode.node.active_download_manager import ActiveDownloadManager
|
||||
from squeaknode.node.node_settings import NodeSettings
|
||||
from squeaknode.node.payment_processor import PaymentProcessor
|
||||
from squeaknode.node.squeak_controller import SqueakController
|
||||
from squeaknode.twitter.twitter_forwarder import TwitterForwarder
|
||||
|
|
@ -58,6 +59,11 @@ def squeak_db():
|
|||
return mock.Mock(spec=SqueakDb)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def node_settings():
|
||||
return mock.Mock(spec=NodeSettings)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def network_manager():
|
||||
return mock.Mock(spec=NetworkManager)
|
||||
|
|
@ -119,6 +125,7 @@ def squeak_controller(
|
|||
network_manager,
|
||||
download_manager,
|
||||
twitter_forwarder,
|
||||
node_settings,
|
||||
config,
|
||||
):
|
||||
return SqueakController(
|
||||
|
|
@ -128,6 +135,7 @@ def squeak_controller(
|
|||
network_manager,
|
||||
download_manager,
|
||||
twitter_forwarder,
|
||||
node_settings,
|
||||
config,
|
||||
)
|
||||
|
||||
|
|
@ -140,6 +148,7 @@ def regtest_squeak_controller(
|
|||
network_manager,
|
||||
download_manager,
|
||||
twitter_forwarder,
|
||||
node_settings,
|
||||
regtest_config,
|
||||
):
|
||||
return SqueakController(
|
||||
|
|
@ -149,6 +158,7 @@ def regtest_squeak_controller(
|
|||
network_manager,
|
||||
download_manager,
|
||||
twitter_forwarder,
|
||||
node_settings,
|
||||
regtest_config,
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue