예제 #1
0
 def setUp(self):
     # Object creation
     self.proposed_trade = Trade.propose(
         TraderId(b'0' * 20), OrderId(TraderId(b'0' * 20), OrderNumber(1)),
         OrderId(TraderId(b'1' * 20), OrderNumber(2)),
         AssetPair(AssetAmount(60, 'BTC'), AssetAmount(30, 'MB')),
         Timestamp(1462224447117))
예제 #2
0
 def test_order_invalid_timeout(self):
     """
     Test whether we cannot create an order with an invalid timeout
     """
     self.nodes[0].overlay.create_ask(
         AssetPair(AssetAmount(10, 'DUM1'), AssetAmount(10, 'DUM2')),
         3600 * 1000)
예제 #3
0
 async def test_order_invalid_timeout(self):
     """
     Test whether we cannot create an order with an invalid timeout
     """
     with self.assertRaises(RuntimeError):
         await self.nodes[0].overlay.create_ask(AssetPair(AssetAmount(10, 'DUM1'),
                                                          AssetAmount(10, 'DUM2')), 3600 * 1000)
예제 #4
0
    def test_next_payment_incremental(self):
        """
        Test the process of determining the next payment details during a transaction with incremental settlement
        """
        self.assertEqual(
            self.transaction.next_payment(True, transfers_per_trade=2),
            AssetAmount(50, 'BTC'))
        self.transaction._current_payment = 0
        self.assertEqual(
            self.transaction.next_payment(False, transfers_per_trade=2),
            AssetAmount(50, 'MB'))
        self.transaction._current_payment = 0

        # Test the edge case
        next_payment = self.transaction.next_payment(True,
                                                     transfers_per_trade=3)
        self.assertEqual(next_payment, AssetAmount(33, 'BTC'))
        self.transaction.transferred_assets.first += next_payment
        next_payment = self.transaction.next_payment(True,
                                                     transfers_per_trade=3)
        self.assertEqual(next_payment, AssetAmount(33, 'BTC'))
        self.transaction.transferred_assets.first += next_payment
        self.assertEqual(
            self.transaction.next_payment(True, transfers_per_trade=3),
            AssetAmount(34, 'BTC'))
예제 #5
0
    def test_e2e_trade_dht(self):
        """
        Test a full trade with (dummy assets), where both traders are not connected to each other
        """
        yield self.introduce_nodes()

        for node in self.nodes:
            for other in self.nodes:
                if other != node:
                    node.dht.walk_to(other.endpoint.wan_address)
        yield self.deliver_messages()

        # Remove the address from the mid registry from the trading peers
        self.nodes[0].overlay.mid_register.pop(
            TraderId(self.nodes[1].overlay.mid))
        self.nodes[1].overlay.mid_register.pop(
            TraderId(self.nodes[0].overlay.mid))

        for node in self.nodes:
            node.dht.store_peer()
        yield self.deliver_messages()

        yield self.nodes[0].overlay.create_ask(
            AssetPair(AssetAmount(10, 'DUM1'), AssetAmount(10, 'DUM2')), 3600)
        yield self.nodes[1].overlay.create_bid(
            AssetPair(AssetAmount(10, 'DUM1'), AssetAmount(10, 'DUM2')), 3600)

        yield self.sleep(0.5)

        # Verify that the trade has been made
        self.assertTrue(
            list(self.nodes[0].overlay.transaction_manager.find_all()))
        self.assertTrue(
            list(self.nodes[1].overlay.transaction_manager.find_all()))
예제 #6
0
    def test_from_network(self):
        # Test for from network
        data = ProposedTrade.from_network(
            type(
                'Data', (object, ), {
                    "trader_id":
                    TraderId(b'0' * 20),
                    "order_number":
                    OrderNumber(1),
                    "recipient_order_id":
                    OrderId(TraderId(b'1' * 20), OrderNumber(2)),
                    "proposal_id":
                    1234,
                    "timestamp":
                    Timestamp(1462224447117),
                    "assets":
                    AssetPair(AssetAmount(60, 'BTC'), AssetAmount(30, 'MB'))
                }))

        self.assertEquals(TraderId(b'0' * 20), data.trader_id)
        self.assertEquals(OrderId(TraderId(b'0' * 20), OrderNumber(1)),
                          data.order_id)
        self.assertEquals(OrderId(TraderId(b'1' * 20), OrderNumber(2)),
                          data.recipient_order_id)
        self.assertEquals(1234, data.proposal_id)
        self.assertEquals(
            AssetPair(AssetAmount(60, 'BTC'), AssetAmount(30, 'MB')),
            data.assets)
        self.assertEquals(Timestamp(1462224447117), data.timestamp)
예제 #7
0
 def from_unpack_list(cls, trader_id, timestamp, order_number, asset1_amount, asset1_type, asset2_amount,
                      asset2_type, timeout, traded, recipient_order_number, match_trader_id, matchmaker_trader_id):
     return MatchPayload(TraderId(trader_id), Timestamp(timestamp), OrderNumber(order_number),
                         AssetPair(AssetAmount(asset1_amount, asset1_type.decode('utf-8')),
                                   AssetAmount(asset2_amount, asset2_type.decode('utf-8'))),
                         Timeout(timeout), traded, OrderNumber(recipient_order_number),
                         TraderId(match_trader_id), TraderId(matchmaker_trader_id))
예제 #8
0
    def from_database(cls, data, payments):
        """
        Create a Transaction object based on information in the database.
        """
        (trader_id, transaction_id, order_number, partner_trader_id, partner_order_number,
         asset1_amount, asset1_type, asset1_transferred, asset2_amount, asset2_type, asset2_transferred,
         transaction_timestamp, sent_wallet_info, received_wallet_info, incoming_address, outgoing_address,
         partner_incoming_address, partner_outgoing_address) = data

        transaction_id = TransactionId(bytes(transaction_id))
        transaction = cls(transaction_id,
                          AssetPair(AssetAmount(asset1_amount, str(asset1_type)),
                                    AssetAmount(asset2_amount, str(asset2_type))),
                          OrderId(TraderId(bytes(trader_id)), OrderNumber(order_number)),
                          OrderId(TraderId(bytes(partner_trader_id)), OrderNumber(partner_order_number)),
                          Timestamp(transaction_timestamp))

        transaction._transferred_assets = AssetPair(AssetAmount(asset1_transferred, str(asset1_type)),
                                                    AssetAmount(asset2_transferred, str(asset2_type)))
        transaction.sent_wallet_info = sent_wallet_info
        transaction.received_wallet_info = received_wallet_info
        transaction.incoming_address = WalletAddress(str(incoming_address))
        transaction.outgoing_address = WalletAddress(str(outgoing_address))
        transaction.partner_incoming_address = WalletAddress(str(partner_incoming_address))
        transaction.partner_outgoing_address = WalletAddress(str(partner_outgoing_address))
        transaction._payments = payments

        return transaction
예제 #9
0
    def test_failing_payment(self):
        """
        Test trading between two persons when a payment fails
        """
        yield self.introduce_nodes()

        for node_nr in [0, 1]:
            self.nodes[node_nr].overlay.wallets[
                'DUM1'].transfer = lambda *_: fail(RuntimeError("oops"))
            self.nodes[node_nr].overlay.wallets[
                'DUM2'].transfer = lambda *_: fail(RuntimeError("oops"))

        yield self.nodes[0].overlay.create_ask(
            AssetPair(AssetAmount(1, 'DUM1'), AssetAmount(1, 'DUM2')), 3600)
        yield self.nodes[1].overlay.create_bid(
            AssetPair(AssetAmount(1, 'DUM1'), AssetAmount(1, 'DUM2')), 3600)

        yield self.sleep(0.5)

        self.assertEqual(
            list(self.nodes[0].overlay.transaction_manager.find_all())
            [0].status, "error")
        self.assertEqual(
            list(self.nodes[1].overlay.transaction_manager.find_all())
            [0].status, "error")
예제 #10
0
async def tick_entry2(price_level):
    tick = Tick(OrderId(TraderId(b'0' * 20), OrderNumber(2)),
                AssetPair(AssetAmount(63400, 'BTC'), AssetAmount(30, 'MB')),
                Timeout(100), Timestamp.now(), True)
    tick_entry = TickEntry(tick, price_level)
    yield tick_entry
    await tick_entry.shutdown_task_manager()
예제 #11
0
    async def match_window_impl(self, test_ask):
        await self.introduce_nodes()

        self.nodes[2].overlay.settings.match_window = 0.5  # Wait 1 sec before accepting (the best) match

        if test_ask:
            order1 = await self.nodes[1].overlay.create_bid(
                AssetPair(AssetAmount(10, 'DUM1'), AssetAmount(10, 'DUM2')), 3600)
            order2 = await self.nodes[0].overlay.create_bid(
                AssetPair(AssetAmount(10, 'DUM1'), AssetAmount(20, 'DUM2')), 3600)
        else:
            order1 = await self.nodes[0].overlay.create_ask(
                AssetPair(AssetAmount(10, 'DUM1'), AssetAmount(10, 'DUM2')), 3600)
            order2 = await self.nodes[1].overlay.create_ask(
                AssetPair(AssetAmount(10, 'DUM1'), AssetAmount(20, 'DUM2')), 3600)

        await sleep(0.2)

        # Make sure that the two matchmaker match different orders
        order1_tick = self.nodes[3].overlay.order_book.get_tick(order1.order_id)
        order2_tick = self.nodes[4].overlay.order_book.get_tick(order2.order_id)
        order1_tick.available_for_matching = 0
        order2_tick.available_for_matching = 0

        if test_ask:
            await self.nodes[2].overlay.create_ask(AssetPair(AssetAmount(10, 'DUM1'), AssetAmount(20, 'DUM2')), 3600)
        else:
            await self.nodes[2].overlay.create_bid(AssetPair(AssetAmount(10, 'DUM1'), AssetAmount(20, 'DUM2')), 3600)

        await sleep(1)

        # Verify that the trade has been made
        self.assertTrue(list(self.nodes[0].overlay.transaction_manager.find_all()))
        self.assertTrue(list(self.nodes[2].overlay.transaction_manager.find_all()))
예제 #12
0
    def __init__(self, transaction_id, assets, order_id, partner_order_id,
                 timestamp):
        """
        :param transaction_id: An transaction id to identify the order
        :param assets: The asset pair to exchange
        :param order_id: The id of your order for this transaction
        :param partner_order_id: The id of the order of the other party
        :param timestamp: A timestamp when the transaction was created
        :type transaction_id: TransactionId
        :type assets: AssetPair
        :type order_id: OrderId
        :type partner_order_id: OrderId
        :type timestamp: Timestamp
        """
        super(Transaction, self).__init__()
        self._logger = logging.getLogger(self.__class__.__name__)

        self._transaction_id = transaction_id
        self._assets = assets
        self._transferred_assets = AssetPair(
            AssetAmount(0, assets.first.asset_id),
            AssetAmount(0, assets.second.asset_id))
        self._order_id = order_id
        self._partner_order_id = partner_order_id
        self._timestamp = timestamp

        self.sent_wallet_info = False
        self.received_wallet_info = False
        self.incoming_address = None
        self.outgoing_address = None
        self.partner_incoming_address = None
        self.partner_outgoing_address = None

        self._payments = []
        self._current_payment = 0
예제 #13
0
    def test_from_network(self):
        # Test for from network
        data = Payment.from_network(
            type(
                'Data', (object, ), {
                    "trader_id":
                    TraderId(b'0' * 20),
                    "transaction_id":
                    TransactionId(TraderId(b'2' * 20), TransactionNumber(2)),
                    "transferred_assets":
                    AssetAmount(3, 'BTC'),
                    "address_from":
                    WalletAddress('a'),
                    "address_to":
                    WalletAddress('b'),
                    "payment_id":
                    PaymentId('aaa'),
                    "timestamp":
                    Timestamp(4000),
                    "success":
                    True
                }))

        self.assertEquals(TraderId(b'0' * 20), data.trader_id)
        self.assertEquals(
            TransactionId(TraderId(b'2' * 20), TransactionNumber(2)),
            data.transaction_id)
        self.assertEquals(AssetAmount(3, 'BTC'), data.transferred_assets)
        self.assertEquals(Timestamp(4000), data.timestamp)
        self.assertTrue(data.success)
예제 #14
0
    def test_from_network(self):
        # Test for from network
        data = StartTransaction.from_network(
            type(
                'Data', (object, ), {
                    "trader_id":
                    TraderId(b'0' * 20),
                    "transaction_id":
                    TransactionId(TraderId(b'0' * 20), TransactionNumber(1)),
                    "order_id":
                    OrderId(TraderId(b'0' * 20), OrderNumber(1)),
                    "recipient_order_id":
                    OrderId(TraderId(b'1' * 20), OrderNumber(2)),
                    "proposal_id":
                    1235,
                    "assets":
                    AssetPair(AssetAmount(30, 'BTC'), AssetAmount(40, 'MC')),
                    "timestamp":
                    Timestamp(0)
                }))

        self.assertEquals(TraderId(b'0' * 20), data.trader_id)
        self.assertEquals(
            TransactionId(TraderId(b'0' * 20), TransactionNumber(1)),
            data.transaction_id)
        self.assertEquals(OrderId(TraderId(b'0' * 20), OrderNumber(1)),
                          data.order_id)
        self.assertEquals(OrderId(TraderId(b'1' * 20), OrderNumber(2)),
                          data.recipient_order_id)
        self.assertEquals(1235, data.proposal_id)
        self.assertEquals(Timestamp(0), data.timestamp)
예제 #15
0
    def test_orderbook_sync(self):
        """
        Test whether orderbooks are synchronized with a new node
        """
        yield self.introduce_nodes()

        ask_order = yield self.nodes[0].overlay.create_ask(
            AssetPair(AssetAmount(1, 'DUM1'), AssetAmount(2, 'DUM2')), 3600)
        bid_order = yield self.nodes[1].overlay.create_bid(
            AssetPair(AssetAmount(1, 'DUM1'), AssetAmount(1, 'DUM2')), 3600)

        yield self.deliver_messages(timeout=.5)

        # Add a node that crawls the matchmaker
        self.add_node_to_experiment(self.create_node())
        self.nodes[3].discovery.take_step()
        yield self.deliver_messages(timeout=.5)
        yield self.sleep(0.2)  # For processing the tick blocks

        self.assertTrue(self.nodes[3].overlay.order_book.get_tick(
            ask_order.order_id))
        self.assertTrue(self.nodes[3].overlay.order_book.get_tick(
            bid_order.order_id))

        # Add another node that crawls our newest node
        self.add_node_to_experiment(self.create_node())
        self.nodes[4].overlay.send_orderbook_sync(
            self.nodes[3].overlay.my_peer)
        yield self.deliver_messages(timeout=.5)
        yield self.sleep(0.2)  # For processing the tick blocks

        self.assertTrue(self.nodes[4].overlay.order_book.get_tick(
            ask_order.order_id))
        self.assertTrue(self.nodes[4].overlay.order_book.get_tick(
            bid_order.order_id))
예제 #16
0
    def test_e2e_trade(self):
        """
        Test a direct trade between two nodes
        """
        yield self.introduce_nodes()

        self.nodes[0].overlay.create_ask(
            AssetPair(AssetAmount(10, 'DUM1'), AssetAmount(13, 'DUM2')), 3600)
        self.nodes[1].overlay.create_bid(
            AssetPair(AssetAmount(10, 'DUM1'), AssetAmount(13, 'DUM2')), 3600)

        yield self.sleep(0.5)

        # Verify that the trade has been made
        self.assertTrue(
            list(self.nodes[0].overlay.transaction_manager.find_all()))
        self.assertTrue(
            list(self.nodes[1].overlay.transaction_manager.find_all()))

        balance1 = yield self.nodes[0].overlay.wallets['DUM1'].get_balance()
        balance2 = yield self.nodes[0].overlay.wallets['DUM2'].get_balance()
        self.assertEqual(balance1['available'], 990)
        self.assertEqual(balance2['available'], 10013)

        balance1 = yield self.nodes[1].overlay.wallets['DUM1'].get_balance()
        balance2 = yield self.nodes[1].overlay.wallets['DUM2'].get_balance()
        self.assertEqual(balance1['available'], 1010)
        self.assertEqual(balance2['available'], 9987)
예제 #17
0
    def from_database(cls, data, reserved_ticks):
        """
        Create an Order object based on information in the database.
        """
        (trader_id, order_number, asset1_amount, asset1_type, asset2_amount,
         asset2_type, traded_quantity, timeout, order_timestamp,
         completed_timestamp, is_ask, cancelled, verified) = data

        order_id = OrderId(TraderId(bytes(trader_id)),
                           OrderNumber(order_number))
        order = cls(
            order_id,
            AssetPair(AssetAmount(asset1_amount, str(asset1_type)),
                      AssetAmount(asset2_amount, str(asset2_type))),
            Timeout(timeout), Timestamp(order_timestamp), bool(is_ask))
        order._traded_quantity = traded_quantity
        order._cancelled = bool(cancelled)
        order._verified = verified
        if completed_timestamp:
            order._completed_timestamp = Timestamp(completed_timestamp)

        for reserved_order_id, quantity in reserved_ticks:
            order.reserved_ticks[reserved_order_id] = quantity
            order._reserved_quantity += quantity

        return order
예제 #18
0
    def test_e2e_trade(self):
        """
        Test trading dummy tokens against bandwidth tokens between two persons, with a matchmaker
        """
        yield self.introduce_nodes()

        yield self.nodes[0].overlay.create_ask(
            AssetPair(AssetAmount(50, 'DUM1'), AssetAmount(50, 'MB')), 3600)
        yield self.nodes[1].overlay.create_bid(
            AssetPair(AssetAmount(50, 'DUM1'), AssetAmount(50, 'MB')), 3600)

        yield self.sleep(0.5)  # Give it some time to complete the trade

        # Verify that the trade has been made
        self.assertTrue(
            list(self.nodes[0].overlay.transaction_manager.find_all()))
        self.assertTrue(
            list(self.nodes[1].overlay.transaction_manager.find_all()))

        balance1 = yield self.nodes[0].overlay.wallets['DUM1'].get_balance()
        balance2 = yield self.nodes[0].overlay.wallets['MB'].get_balance()
        self.assertEqual(balance1['available'], 950)
        self.assertEqual(balance2['available'], 50)

        balance1 = yield self.nodes[1].overlay.wallets['DUM1'].get_balance()
        balance2 = yield self.nodes[1].overlay.wallets['MB'].get_balance()
        self.assertEqual(balance1['available'], 1050)
        self.assertEqual(balance2['available'], -50)
예제 #19
0
def test_init():
    """
    Test the initialization of a price
    """
    with pytest.raises(ValueError):
        AssetAmount('1', 'MC')
    with pytest.raises(ValueError):
        AssetAmount(1, 2)
예제 #20
0
def insert_bid(order_book, amount1, amount2):
    """
    Insert a bid with a specific price and quantity
    """
    new_bid = Bid(OrderId(TraderId(b'3' * 20), OrderNumber(len(order_book.bids) + 1)),
                  AssetPair(AssetAmount(amount1, 'BTC'), AssetAmount(amount2, 'MB')), Timeout(30), Timestamp.now())
    order_book.insert_bid(new_bid)
    return new_bid
예제 #21
0
def insert_ask(order_book, amount1, amount2):
    """
    Insert an ask in the order book with a specific price and quantity
    """
    new_ask = Ask(OrderId(TraderId(b'2' * 20), OrderNumber(len(order_book.asks) + 1)),
                  AssetPair(AssetAmount(amount1, 'BTC'), AssetAmount(amount2, 'MB')), Timeout(30), Timestamp.now())
    order_book.insert_ask(new_ask)
    return new_ask
예제 #22
0
 def test_next_payment(self):
     """
     Test the process of determining the next payment details during a transaction
     """
     self.assertEqual(self.transaction.next_payment(True),
                      AssetAmount(100, 'BTC'))
     self.assertEqual(self.transaction.next_payment(False),
                      AssetAmount(100, 'MB'))
예제 #23
0
def order2():
    order_id2 = OrderId(TraderId(b'4' * 20), OrderNumber(5))
    order2 = Order(order_id2,
                   AssetPair(AssetAmount(5, 'BTC'), AssetAmount(6, 'EUR')),
                   Timeout(3600), Timestamp.now(), False)
    order2.reserve_quantity_for_tick(
        OrderId(TraderId(b'3' * 20), OrderNumber(4)), 3)
    return order2
 def setUp(self):
     # Object creation
     self.memory_order_repository = MemoryOrderRepository(b'0' * 20)
     self.order_id = OrderId(TraderId(b'0' * 20), OrderNumber(1))
     self.order = Order(self.order_id, AssetPair(AssetAmount(100, 'BTC'), AssetAmount(30, 'MC')),
                        Timeout(0), Timestamp(10), False)
     self.order2 = Order(self.order_id, AssetPair(AssetAmount(1000, 'BTC'), AssetAmount(30, 'MC')),
                         Timeout(0), Timestamp(10), False)
예제 #25
0
 def test_to_network(self):
     # Test for to network
     self.assertEquals(
         (TraderId(b'0' * 20), Timestamp(1462224447117), OrderNumber(1),
          OrderId(TraderId(b'1' * 20),
                  OrderNumber(2)), self.proposed_trade.proposal_id,
          AssetPair(AssetAmount(60, 'BTC'), AssetAmount(30, 'MB'))),
         self.proposed_trade.to_network())
예제 #26
0
 def test_init(self):
     """
     Test the initialization of a price
     """
     with self.assertRaises(ValueError):
         AssetAmount('1', 'MC')
     with self.assertRaises(ValueError):
         AssetAmount(1, 2)
예제 #27
0
 def from_unpack_list(cls, trader_id, timestamp, order_number,
                      asset1_amount, asset1_type, asset2_amount,
                      asset2_type, timeout, traded, identifier):
     return OrderStatusResponsePayload(
         TraderId(trader_id), Timestamp(timestamp),
         OrderNumber(order_number),
         AssetPair(AssetAmount(asset1_amount, asset1_type.decode('utf-8')),
                   AssetAmount(asset2_amount, asset2_type.decode('utf-8'))),
         Timeout(timeout), traded, identifier)
예제 #28
0
 async def test_create_invalid_ask_bid(self):
     """
     Test creating an invalid ask/bid with invalid asset pairs.
     """
     invalid_pair = AssetPair(AssetAmount(1, 'DUM2'), AssetAmount(2, 'DUM2'))
     with self.assertRaises(RuntimeError):
         await self.nodes[0].overlay.create_ask(invalid_pair, 3600)
     with self.assertRaises(RuntimeError):
         await self.nodes[0].overlay.create_bid(invalid_pair, 3600)
예제 #29
0
 def setUp(self):
     # Object creation
     self.start_transaction = StartTransaction(
         TraderId(b'0' * 20),
         TransactionId(TraderId(b'0' * 20), TransactionNumber(1)),
         OrderId(TraderId(b'0' * 20), OrderNumber(1)),
         OrderId(TraderId(b'1' * 20), OrderNumber(1)), 1234,
         AssetPair(AssetAmount(30, 'BTC'), AssetAmount(40, 'MC')),
         Timestamp(0))
예제 #30
0
 def from_unpack_list(cls, trader_id, timestamp, tx_trader_id, transaction_number,
                      order_trader_id, order_number, recipient_trader_id, recipient_order_number, proposal_id,
                      asset1_amount, asset1_type, asset2_amount, asset2_type):
     return StartTransactionPayload(TraderId(trader_id), Timestamp(timestamp),
                                    TransactionId(TraderId(tx_trader_id), TransactionNumber(transaction_number)),
                                    OrderId(TraderId(order_trader_id), OrderNumber(order_number)),
                                    OrderId(TraderId(recipient_trader_id), OrderNumber(recipient_order_number)),
                                    proposal_id, AssetPair(AssetAmount(asset1_amount, asset1_type.decode('utf-8')),
                                                           AssetAmount(asset2_amount, asset2_type.decode('utf-8'))))