def test_apply(): """Test the apply function.""" currency_endowment = {"FET": 100} good_endowment = {"good_id": 2} ownership_state = OwnershipState( amount_by_currency_id=currency_endowment, quantities_by_good_id=good_endowment, ) tx_message = TransactionMessage( performative=TransactionMessage.Performative.PROPOSE_FOR_SETTLEMENT, skill_callback_ids=[PublicId(AUTHOR, "a_skill", "0.1.0")], tx_id="transaction0", tx_sender_addr="agent_1", tx_counterparty_addr="pk", tx_amount_by_currency_id={"FET": -20}, tx_sender_fee=5, tx_counterparty_fee=0, tx_quantities_by_good_id={"good_id": 10}, info={"some_info_key": "some_info_value"}, ledger_id="fetchai", tx_nonce="transaction nonce", ) list_of_transactions = [tx_message] state = ownership_state new_state = ownership_state.apply_transactions( transactions=list_of_transactions) assert ( state != new_state ), "after applying a list_of_transactions must have a different state!"
def test_transaction_is_affordable_agent_is_buyer(): """Check if the agent has the money to cover the sender_amount (the agent=sender is the buyer).""" currency_endowment = {"FET": 100} good_endowment = {"good_id": 20} ownership_state = OwnershipState( amount_by_currency_id=currency_endowment, quantities_by_good_id=good_endowment, ) tx_message = TransactionMessage( performative=TransactionMessage.Performative.PROPOSE_FOR_SETTLEMENT, skill_callback_ids=[PublicId(AUTHOR, "a_skill", "0.1.0")], tx_id="transaction0", tx_sender_addr="agent_1", tx_counterparty_addr="pk", tx_amount_by_currency_id={"FET": -1}, tx_sender_fee=0, tx_counterparty_fee=0, tx_quantities_by_good_id={"good_id": 10}, info={"some_info_key": "some_info_value"}, ledger_id="fetchai", tx_nonce="transaction nonce", ) assert ownership_state.is_affordable_transaction( tx_message=tx_message), "We should have the money for the transaction!"
def test_transaction_update_receive(): """Test the transaction update when receiving tokens.""" currency_endowment = {"FET": 75} good_endowment = {"good_id": 30} ownership_state = OwnershipState( amount_by_currency_id=currency_endowment, quantities_by_good_id=good_endowment, ) assert ownership_state.amount_by_currency_id == currency_endowment assert ownership_state.quantities_by_good_id == good_endowment tx_message = TransactionMessage( performative=TransactionMessage.Performative.PROPOSE_FOR_SETTLEMENT, skill_callback_ids=[PublicId(AUTHOR, "a_skill", "0.1.0")], tx_id="transaction0", tx_sender_addr="agent_1", tx_counterparty_addr="pk", tx_amount_by_currency_id={"FET": 20}, tx_sender_fee=5, tx_counterparty_fee=0, tx_quantities_by_good_id={"good_id": -10}, info={"some_info_key": "some_info_value"}, ledger_id="fetchai", tx_nonce="transaction nonce", ) ownership_state._update(tx_message=tx_message) expected_amount_by_currency_id = {"FET": 90} expected_quantities_by_good_id = {"good_id": 20} assert ownership_state.amount_by_currency_id == expected_amount_by_currency_id assert ownership_state.quantities_by_good_id == expected_quantities_by_good_id
def test_transaction_is_affordable_there_is_no_wealth(): """Reject the transaction when there is no wealth exchange.""" currency_endowment = {"FET": 0} good_endowment = {"good_id": 0} ownership_state = OwnershipState( amount_by_currency_id=currency_endowment, quantities_by_good_id=good_endowment, ) tx_message = TransactionMessage( performative=TransactionMessage.Performative.PROPOSE_FOR_SETTLEMENT, skill_callback_ids=[PublicId(AUTHOR, "a_skill", "0.1.0")], tx_id="transaction0", tx_sender_addr="agent_1", tx_counterparty_addr="pk", tx_amount_by_currency_id={"FET": 0}, tx_sender_fee=0, tx_counterparty_fee=0, tx_quantities_by_good_id={"good_id": 0}, info={"some_info_key": "some_info_value"}, ledger_id="fetchai", tx_nonce="transaction nonce", ) assert not ownership_state.is_affordable_transaction( tx_message=tx_message), "We must reject the transaction."
def tests_transaction_is_affordable_else_statement(): """Check that the function returns false if we cannot satisfy any if/elif statements.""" currency_endowment = {"FET": 0} good_endowment = {"good_id": 0} ownership_state = OwnershipState( amount_by_currency_id=currency_endowment, quantities_by_good_id=good_endowment, ) tx_message = TransactionMessage( performative=TransactionMessage.Performative.PROPOSE_FOR_SETTLEMENT, skill_callback_ids=[PublicId(AUTHOR, "a_skill", "0.1.0")], tx_id="transaction0", tx_sender_addr="agent_1", tx_counterparty_addr="pk", tx_amount_by_currency_id={"FET": 10}, tx_sender_fee=0, tx_counterparty_fee=0, tx_quantities_by_good_id={"good_id": 50}, info={"some_info_key": "some_info_value"}, ledger_id="fetchai", tx_nonce="transaction nonce", ) assert not ownership_state.is_affordable_transaction( tx_message=tx_message), "We must reject the transaction."
def test_marginal_utility(): """Test the marginal utility.""" currency_holdings = {"FET": 100} utility_params = {"good_id": 20.0} exchange_params = {"FET": 10.0} good_holdings = {"good_id": 2} tx_fee = 9 preferences = Preferences() preferences.init( utility_params_by_good_id=utility_params, exchange_params_by_currency_id=exchange_params, tx_fee=tx_fee, ) ownership_state = OwnershipState() delta_good_holdings = {"good_id": 1} delta_currency_holdings = {"FET": -5} ownership_state.init( amount_by_currency_id=currency_holdings, quantities_by_good_id=good_holdings, ) marginal_utility = preferences.marginal_utility( ownership_state=ownership_state, delta_quantities_by_good_id=delta_good_holdings, delta_amount_by_currency_id=delta_currency_holdings, ) assert marginal_utility is not None, "Marginal utility must not be none."
def test_initialisation(): """Test the initialisation of the ownership_state.""" ownership_state = OwnershipState() currency_endowment = {"FET": 100} good_endowment = {"good_id": 2} ownership_state.init( amount_by_currency_id=currency_endowment, quantities_by_good_id=good_endowment, ) assert ownership_state.amount_by_currency_id is not None assert ownership_state.quantities_by_good_id is not None assert ownership_state.is_initialized
def is_profitable_transaction(self, preferences: Preferences, ownership_state_after_locks: OwnershipState, transaction_msg: TransactionMessage) -> bool: """ Check if a transaction is profitable. Is it a profitable transaction? - apply all the locks for role. - check if the transaction is consistent with the locks (enough money/holdings) - check that we gain score. :param preferences: the preferences of the agent :param ownership_state_after_locks: the ownership state after the transaction messages applied. :param transaction_msg: the transaction_msg :return: True if the transaction is good (as stated above), False otherwise. """ if not ownership_state_after_locks.check_transaction_is_consistent( transaction_msg): return False proposal_delta_score = preferences.get_score_diff_from_transaction( ownership_state_after_locks, transaction_msg) if proposal_delta_score >= 0: return True else: return False
def setup_class(cls): """Initialise the decision maker.""" cls._patch_logger() cls.multiplexer = Multiplexer([_make_dummy_connection()]) private_key_pem_path = os.path.join(CUR_PATH, "data", "fet_private_key.txt") eth_private_key_pem_path = os.path.join(CUR_PATH, "data", "fet_private_key.txt") cls.wallet = Wallet({ FETCHAI: private_key_pem_path, ETHEREUM: eth_private_key_pem_path }) cls.ledger_apis = LedgerApis({FETCHAI: DEFAULT_FETCHAI_CONFIG}, FETCHAI) cls.agent_name = "test" cls.identity = Identity(cls.agent_name, addresses=cls.wallet.addresses, default_address_key=FETCHAI) cls.ownership_state = OwnershipState() cls.preferences = Preferences() cls.decision_maker = DecisionMaker( identity=cls.identity, wallet=cls.wallet, ledger_apis=cls.ledger_apis, ) cls.multiplexer.connect() cls.tx_id = "transaction0" cls.tx_sender_addr = "agent_1" cls.tx_counterparty_addr = "pk" cls.info = {"some_info_key": "some_info_value"} cls.ledger_id = "fetchai" cls.decision_maker.start()
def setup_class(cls): """Initialise the decision maker.""" cls._patch_logger() cls.multiplexer = Multiplexer( [DummyConnection(connection_id=DUMMY_CONNECTION_PUBLIC_ID)]) cls.outbox = OutBox(cls.multiplexer) private_key_pem_path = os.path.join(CUR_PATH, "data", "fet_private_key.txt") eth_private_key_pem_path = os.path.join(CUR_PATH, "data", "fet_private_key.txt") cls.wallet = Wallet({ FETCHAI: private_key_pem_path, ETHEREUM: eth_private_key_pem_path }) cls.ledger_apis = LedgerApis({FETCHAI: DEFAULT_FETCHAI_CONFIG}, FETCHAI) cls.agent_name = "test" cls.ownership_state = OwnershipState() cls.preferences = Preferences() cls.decision_maker = DecisionMaker( agent_name=cls.agent_name, max_reactions=MAX_REACTIONS, outbox=cls.outbox, wallet=cls.wallet, ledger_apis=cls.ledger_apis, ) cls.multiplexer.connect() cls.tx_id = "transaction0" cls.tx_sender_addr = "agent_1" cls.tx_counterparty_addr = "pk" cls.info = {"some_info_key": "some_info_value"} cls.ledger_id = "fetchai" cls.decision_maker.start()
def test_non_initialized_ownership_state_raises_exception(): """Test that non-initialized ownership state raises exception.""" ownership_state = OwnershipState() with pytest.raises(AssertionError): ownership_state.amount_by_currency_id with pytest.raises(AssertionError): ownership_state.quantities_by_good_id
def test_score_diff_from_transaction(): """Test the difference between the scores.""" good_holdings = {"good_id": 2} currency_holdings = {"FET": 100} utility_params = {"good_id": 20.0} exchange_params = {"FET": 10.0} tx_fee = 3 preferences = Preferences() ownership_state = OwnershipState() ownership_state.init(amount_by_currency_id=currency_holdings, quantities_by_good_id=good_holdings) preferences.init( utility_params_by_good_id=utility_params, exchange_params_by_currency_id=exchange_params, tx_fee=tx_fee, ) tx_message = TransactionMessage( performative=TransactionMessage.Performative.PROPOSE_FOR_SETTLEMENT, skill_callback_ids=[PublicId(AUTHOR, "a_skill", "0.1.0")], tx_id="transaction0", tx_sender_addr="agent_1", tx_counterparty_addr="pk", tx_amount_by_currency_id={"FET": -20}, tx_sender_fee=preferences.transaction_fees["seller_tx_fee"], tx_counterparty_fee=preferences.transaction_fees["buyer_tx_fee"], tx_quantities_by_good_id={"good_id": 10}, info={"some_info_key": "some_info_value"}, ledger_id="fetchai", tx_nonce="transaction nonce", ) cur_score = preferences.get_score(quantities_by_good_id=good_holdings, amount_by_currency_id=currency_holdings) new_state = ownership_state.apply_transactions([tx_message]) new_score = preferences.get_score( quantities_by_good_id=new_state.quantities_by_good_id, amount_by_currency_id=new_state.amount_by_currency_id, ) dif_scores = new_score - cur_score score_difference = preferences.get_score_diff_from_transaction( ownership_state=ownership_state, tx_message=tx_message) assert ( score_difference == dif_scores ), "The calculated difference must be equal to the return difference from the function."
def ownership_state_after_locks(self, ownership_state: OwnershipState, is_seller: bool) -> OwnershipState: """ Apply all the locks to the current ownership state of the agent. This assumes, that all the locked transactions will be successful. :param is_seller: Boolean indicating the role of the agent. :return: the agent state with the locks applied to current state """ transaction_msgs = list( self._locked_txs_as_seller.values()) if is_seller else list( self._locked_txs_as_buyer.values()) ownershio_state_after_locks = ownership_state.apply(transaction_msgs) return ownershio_state_after_locks
def setup_class(cls): """Initialise the decision maker.""" cls._patch_logger() cls.multiplexer = Multiplexer([DummyConnection()]) cls.outbox = OutBox(cls.multiplexer) private_key_pem_path = os.path.join(CUR_PATH, "data", "fet_private_key.txt") cls.wallet = Wallet({FETCHAI: private_key_pem_path}) cls.ledger_apis = LedgerApis({FETCHAI: DEFAULT_FETCHAI_CONFIG}) cls.agent_name = "test" cls.ownership_state = OwnershipState() cls.preferences = Preferences() cls.decision_maker = DecisionMaker(agent_name=cls.agent_name, max_reactions=MAX_REACTIONS, outbox=cls.outbox, wallet=cls.wallet, ledger_apis=cls.ledger_apis) cls.multiplexer.connect()
def utility_diff_from_transaction(self, ownership_state: BaseOwnershipState, terms: Terms) -> float: """ Simulate a transaction and get the resulting utility difference (taking into account the fee). :param ownership_state: the ownership state against which to apply the transaction. :param terms: the transaction terms. :return: the score. """ assert self.is_initialized, "Preferences params not set!" ownership_state = cast(OwnershipState, ownership_state) current_score = self.utility( quantities_by_good_id=ownership_state.quantities_by_good_id, amount_by_currency_id=ownership_state.amount_by_currency_id, ) new_ownership_state = ownership_state.apply_transactions([terms]) new_score = self.utility( quantities_by_good_id=new_ownership_state.quantities_by_good_id, amount_by_currency_id=new_ownership_state.amount_by_currency_id, ) score_difference = new_score - current_score return score_difference
def setup_class(cls): """Initialise the class.""" cls.ownership_state = OwnershipState() cls.preferences = Preferences()