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))
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)
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)
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'))
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()))
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)
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))
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
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")
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()
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()))
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
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)
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)
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))
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)
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
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)
def test_init(): """ Test the initialization of a price """ with pytest.raises(ValueError): AssetAmount('1', 'MC') with pytest.raises(ValueError): AssetAmount(1, 2)
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
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
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'))
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)
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())
def test_init(self): """ Test the initialization of a price """ with self.assertRaises(ValueError): AssetAmount('1', 'MC') with self.assertRaises(ValueError): AssetAmount(1, 2)
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)
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)
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))
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'))))