mirror of
https://github.com/yzernik/squeaknode.git
synced 2026-08-18 13:09:08 +02:00
Add price policy class to determine sell price (#1785)
This commit is contained in:
parent
581ef4f226
commit
c96f7c7f7f
3 changed files with 163 additions and 10 deletions
65
squeaknode/node/price_policy.py
Normal file
65
squeaknode/node/price_policy.py
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
# 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 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.squeak_profile import SqueakProfile
|
||||
from squeaknode.db.squeak_db import SqueakDb
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PricePolicy:
|
||||
|
||||
def __init__(self, squeak_db: SqueakDb, config: SqueaknodeConfig):
|
||||
self.squeak_db = squeak_db
|
||||
self.config = config
|
||||
|
||||
def get_price(self, squeak: CSqueak, peer_address: PeerAddress) -> int:
|
||||
"""Get the price to sell this squeak to this peer.
|
||||
|
||||
"""
|
||||
# Return zero for price if peer is configured to be share for free.
|
||||
peer = self.get_peer(peer_address)
|
||||
if peer is not None and peer.share_for_free:
|
||||
return 0
|
||||
# Return custom price if address is configured with custom price.
|
||||
squeak_address = str(squeak.GetAddress())
|
||||
squeak_profile = self.get_profile(squeak_address)
|
||||
if squeak_profile is not None and squeak_profile.use_custom_price:
|
||||
return squeak_profile.custom_price_msat
|
||||
return self.get_default_price()
|
||||
|
||||
def get_peer(self, peer_address: PeerAddress) -> Optional[SqueakPeer]:
|
||||
return self.squeak_db.get_peer_by_address(peer_address)
|
||||
|
||||
def get_profile(self, address: str) -> Optional[SqueakProfile]:
|
||||
return self.squeak_db.get_profile_by_address(address)
|
||||
|
||||
def get_default_price(self) -> int:
|
||||
return self.config.node.price_msat
|
||||
|
|
@ -65,6 +65,7 @@ from squeaknode.core.update_twitter_stream_event import UpdateTwitterStreamEvent
|
|||
from squeaknode.core.user_config import UserConfig
|
||||
from squeaknode.node.active_download_manager import ActiveDownload
|
||||
from squeaknode.node.listener_subscription_client import EventListener
|
||||
from squeaknode.node.price_policy import PricePolicy
|
||||
from squeaknode.node.received_payments_subscription_client import ReceivedPaymentsSubscriptionClient
|
||||
|
||||
|
||||
|
|
@ -232,16 +233,8 @@ class SqueakController:
|
|||
return sent_offer
|
||||
|
||||
def get_price_for_squeak(self, squeak: CSqueak, peer_address: PeerAddress) -> int:
|
||||
# Return zero for price if peer is configured to be share for free.
|
||||
peer = self.squeak_db.get_peer_by_address(peer_address)
|
||||
if peer is not None and peer.share_for_free:
|
||||
return 0
|
||||
# Return custom price if address is configured with custom price.
|
||||
squeak_address = str(squeak.GetAddress())
|
||||
squeak_profile = self.get_squeak_profile_by_address(squeak_address)
|
||||
if squeak_profile is not None and squeak_profile.use_custom_price:
|
||||
return squeak_profile.custom_price_msat
|
||||
return self.config.node.price_msat
|
||||
price_policy = PricePolicy(self.squeak_db, self.config)
|
||||
return price_policy.get_price(squeak, peer_address)
|
||||
|
||||
def create_signing_profile(self, profile_name: str) -> int:
|
||||
squeak_profile = create_signing_profile(
|
||||
|
|
|
|||
95
tests/node/test_price_policy.py
Normal file
95
tests/node/test_price_policy.py
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
# 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 mock
|
||||
import pytest
|
||||
|
||||
from squeaknode.node.price_policy import PricePolicy
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def price_policy():
|
||||
yield PricePolicy(None, None)
|
||||
|
||||
|
||||
def test_get_price(price_policy, squeak, peer_address):
|
||||
with mock.patch.object(price_policy, 'get_peer', autospec=True) as mock_get_peer, \
|
||||
mock.patch.object(price_policy, 'get_profile', autospec=True) as mock_get_profile, \
|
||||
mock.patch.object(price_policy, 'get_default_price', autospec=True) as mock_get_default_price:
|
||||
mock_get_peer.return_value = None
|
||||
mock_get_profile.return_value = None
|
||||
mock_get_default_price.return_value = 555
|
||||
|
||||
assert price_policy.get_price(squeak, peer_address) == 555
|
||||
|
||||
|
||||
def test_get_price_profile_custom_price(price_policy, squeak, peer_address, signing_profile):
|
||||
with mock.patch.object(price_policy, 'get_peer', autospec=True) as mock_get_peer, \
|
||||
mock.patch.object(price_policy, 'get_profile', autospec=True) as mock_get_profile, \
|
||||
mock.patch.object(price_policy, 'get_default_price', autospec=True) as mock_get_default_price:
|
||||
mock_get_peer.return_value = None
|
||||
mock_get_profile.return_value = signing_profile._replace(
|
||||
use_custom_price=True,
|
||||
custom_price_msat=54321,
|
||||
)
|
||||
mock_get_default_price.return_value = 555
|
||||
|
||||
assert price_policy.get_price(squeak, peer_address) == 54321
|
||||
|
||||
|
||||
def test_get_price_profile_no_custom_price(price_policy, squeak, peer_address, signing_profile):
|
||||
with mock.patch.object(price_policy, 'get_peer', autospec=True) as mock_get_peer, \
|
||||
mock.patch.object(price_policy, 'get_profile', autospec=True) as mock_get_profile, \
|
||||
mock.patch.object(price_policy, 'get_default_price', autospec=True) as mock_get_default_price:
|
||||
mock_get_peer.return_value = None
|
||||
mock_get_profile.return_value = signing_profile._replace(
|
||||
use_custom_price=False,
|
||||
custom_price_msat=54321,
|
||||
)
|
||||
mock_get_default_price.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):
|
||||
with mock.patch.object(price_policy, 'get_peer', autospec=True) as mock_get_peer, \
|
||||
mock.patch.object(price_policy, 'get_profile', autospec=True) as mock_get_profile, \
|
||||
mock.patch.object(price_policy, 'get_default_price', autospec=True) as mock_get_default_price:
|
||||
mock_get_peer.return_value = peer._replace(
|
||||
share_for_free=True,
|
||||
)
|
||||
mock_get_profile.return_value = None
|
||||
mock_get_default_price.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):
|
||||
with mock.patch.object(price_policy, 'get_peer', autospec=True) as mock_get_peer, \
|
||||
mock.patch.object(price_policy, 'get_profile', autospec=True) as mock_get_profile, \
|
||||
mock.patch.object(price_policy, 'get_default_price', autospec=True) as mock_get_default_price:
|
||||
mock_get_peer.return_value = peer._replace(
|
||||
share_for_free=False,
|
||||
)
|
||||
mock_get_profile.return_value = None
|
||||
mock_get_default_price.return_value = 555
|
||||
|
||||
assert price_policy.get_price(squeak, peer_address) == 555
|
||||
Loading…
Add table
Add a link
Reference in a new issue