diff --git a/Tribler/Core/Modules/restapi/wallets_endpoint.py b/Tribler/Core/Modules/restapi/wallets_endpoint.py
index 4d99096d547..4c3e067a755 100644
--- a/Tribler/Core/Modules/restapi/wallets_endpoint.py
+++ b/Tribler/Core/Modules/restapi/wallets_endpoint.py
@@ -234,13 +234,13 @@ def render_POST(self, request):
"""
.. http:get:: /wallets/(string:wallet identifier)/transfer
- A GET request to this endpoint will return past transactions of a specific wallet.
+ A POST request to this endpoint will transfer some units from a wallet to another address.
**Example request**:
.. sourcecode:: none
- curl -X GET http://localhost:8085/wallets/BTC/transfer
+ curl -X POST http://localhost:8085/wallets/BTC/transfer
--data "amount=0.3&destination=mpC1DDgSP4PKc5HxJzQ5w9q6CGLBEQuLsN"
**Example response**:
diff --git a/Tribler/Test/Community/Market/Wallet/test_btc_wallet.py b/Tribler/Test/Community/Market/Wallet/test_btc_wallet.py
index 5e5ae5f5b26..915c226fd59 100644
--- a/Tribler/Test/Community/Market/Wallet/test_btc_wallet.py
+++ b/Tribler/Test/Community/Market/Wallet/test_btc_wallet.py
@@ -1,3 +1,4 @@
+from jsonrpclib import ProtocolError
from twisted.internet.defer import inlineCallbacks, succeed, Deferred
from Tribler.Test.Core.base_test import MockObject
@@ -143,8 +144,43 @@ def test_get_transactions(self):
wallet = BitcoinWallet(self.session_base_dir)
mock_daemon = MockObject()
mock_server = MockObject()
- transactions = [{'value': -1, 'txid': 'a', 'timestamp': 1}, {'value': 1, 'txid': 'a', 'timestamp': 1}]
+ transactions = [{
+ 'value': -1,
+ 'txid': 'a',
+ 'timestamp': 1,
+ 'input_addresses': ['a', 'b'],
+ 'output_addresses': ['c', 'd'],
+ 'confirmations': 3
+ }, {
+ 'value': 1,
+ 'txid': 'b',
+ 'timestamp': False, # In Electrum, this means that the transaction has not been confirmed yet
+ 'input_addresses': ['a', 'b'],
+ 'output_addresses': ['c', 'd'],
+ 'confirmations': 0
+ }]
mock_server.run_cmdline = lambda _: transactions
mock_daemon.get_server = lambda _: mock_server
wallet.get_daemon = lambda: mock_daemon
return wallet.get_transactions()
+
+ @deferred(timeout=10)
+ def test_get_transactions_error(self):
+ """
+ Test whether no transactions are returned when there's a protocol in the JSON RPC protocol
+ """
+ wallet = BitcoinWallet(self.session_base_dir)
+ mock_daemon = MockObject()
+ mock_server = MockObject()
+
+ def failing_run_cmdline(*_):
+ raise ProtocolError()
+
+ mock_server.run_cmdline = failing_run_cmdline
+ mock_daemon.get_server = lambda _: mock_server
+ wallet.get_daemon = lambda: mock_daemon
+
+ def verify_transactions(transactions):
+ self.assertFalse(transactions)
+
+ return wallet.get_transactions().addCallback(verify_transactions)
diff --git a/Tribler/Test/Community/Market/test_trade.py b/Tribler/Test/Community/Market/test_trade.py
index 9bfcc619887..6c380f8d252 100644
--- a/Tribler/Test/Community/Market/test_trade.py
+++ b/Tribler/Test/Community/Market/test_trade.py
@@ -22,7 +22,6 @@ def test_to_network(self):
# Test for to network
self.assertEquals(NotImplemented, self.trade.to_network())
-
class ProposedTradeTestSuite(unittest.TestCase):
"""Proposed trade test cases."""
@@ -61,6 +60,19 @@ def test_from_network(self):
self.assertEquals(Quantity(30, 'MC'), data.quantity)
self.assertEquals(Timestamp(1462224447.117), data.timestamp)
+ def test_has_acceptable_price(self):
+ """
+ Test the acceptable price method
+ """
+ self.assertTrue(self.proposed_trade.has_acceptable_price(True, Price(63000, 'BTC')))
+ self.assertFalse(self.proposed_trade.has_acceptable_price(False, Price(63000, 'BTC')))
+ self.assertTrue(self.proposed_trade.has_acceptable_price(False, Price(64000, 'BTC')))
+ self.assertFalse(self.proposed_trade.has_acceptable_price(True, Price(64000, 'BTC')))
+
+ # Test a price close to the proposed price
+ self.assertTrue(self.proposed_trade.has_acceptable_price(False, Price(63400.0 - 1e-07, 'BTC')))
+ self.assertTrue(self.proposed_trade.has_acceptable_price(True, Price(63400.0 - 1e-07, 'BTC')))
+
class DeclinedTradeTestSuite(unittest.TestCase):
"""Declined trade test cases."""
diff --git a/Tribler/community/market/community.py b/Tribler/community/market/community.py
index 80ee65c366a..84de651fd26 100644
--- a/Tribler/community/market/community.py
+++ b/Tribler/community/market/community.py
@@ -1033,10 +1033,10 @@ def received_proposed_trade(self, _, data):
declined_trade = Trade.decline(self.message_repository.next_identity(),
Timestamp.now(), proposed_trade, decline_reason)
self.logger.debug("Declined trade made with id: %s for proposed trade with id: %s "
- "(valid? %s, available quantity of order: %s, reserved: %s, traded: %s)",
+ "(valid? %s, available quantity of order: %s, reserved: %s, traded: %s), reason: %s",
str(declined_trade.message_id), str(proposed_trade.message_id),
order.is_valid(), order.available_quantity, order.reserved_quantity,
- order.traded_quantity)
+ order.traded_quantity, decline_reason)
self.send_declined_trade(declined_trade)
else:
self.logger.debug("Proposed trade received with id: %s for order with id: %s",
diff --git a/Tribler/community/market/core/trade.py b/Tribler/community/market/core/trade.py
index 8bec7f73739..4d9807bac7c 100644
--- a/Tribler/community/market/core/trade.py
+++ b/Tribler/community/market/core/trade.py
@@ -221,7 +221,13 @@ def has_acceptable_price(self, is_ask, order_price):
Return whether this trade proposal has an acceptable price.
:rtype: bool
"""
- return (is_ask and self.price >= order_price) or (not is_ask and self.price <= order_price)
+ def isclose(price_a, price_b):
+ price_a = float(price_a)
+ price_b = float(price_b)
+ return abs(price_a - price_b) <= 1e-06
+
+ return (is_ask and (self.price >= order_price or isclose(self.price, order_price))) or \
+ (not is_ask and (self.price <= order_price or isclose(self.price, order_price)))
def to_network(self):
"""
diff --git a/Tribler/community/market/wallet/btc_wallet.py b/Tribler/community/market/wallet/btc_wallet.py
index 0b945e30fa0..82f4b22906c 100644
--- a/Tribler/community/market/wallet/btc_wallet.py
+++ b/Tribler/community/market/wallet/btc_wallet.py
@@ -5,6 +5,7 @@
import imp
import keyring
from Tribler.Core.Utilities.install_dir import get_base_path
+from jsonrpclib import ProtocolError
from twisted.internet.defer import Deferred, succeed, fail, inlineCallbacks
from twisted.internet.task import LoopingCall
@@ -150,12 +151,23 @@ def get_balance(self):
"""
Return the balance of the wallet.
"""
- divider = 100000000
if self.created:
- confirmed, unconfirmed, unmatured = self.wallet.get_balance()
+ options = {'nolnet': False, 'password': None, 'verbose': False, 'cmd': 'getbalance',
+ 'wallet_path': self.wallet_file, 'testnet': self.testnet, 'segwit': False,
+ 'cwd': self.wallet_dir,
+ 'portable': False}
+ config = SimpleConfig(options)
+
+ server = self.get_daemon().get_server(config)
+ result = server.run_cmdline(options)
+
+ confirmed = float(result['confirmed'])
+ unconfirmed = float(result['unconfirmed']) if 'unconfirmed' in result else 0
+ unconfirmed += (float(result['unmatured']) if 'unmatured' in result else 0)
+
return succeed({
- "available": float(confirmed) / divider,
- "pending": float(unconfirmed + unmatured) / divider,
+ "available": confirmed,
+ "pending": unconfirmed,
"currency": 'BTC'
})
else:
@@ -226,17 +238,17 @@ def get_transactions(self):
config = SimpleConfig(options)
server = self.get_daemon().get_server(config)
- result = server.run_cmdline(options)
+ try:
+ result = server.run_cmdline(options)
+ except ProtocolError:
+ self._logger.error("Unable to fetch transactions from BTC wallet!")
+ return succeed([])
transactions = []
for transaction in result:
outgoing = transaction['value'] < 0
- if outgoing:
- from_address = self.get_address()
- to_address = ''
- else:
- from_address = ''
- to_address = self.get_address()
+ from_address = ','.join(transaction['input_addresses'])
+ to_address = ','.join(transaction['output_addresses'])
transactions.append({
'id': transaction['txid'],
diff --git a/TriblerGUI/qt_resources/mainwindow.ui b/TriblerGUI/qt_resources/mainwindow.ui
index 36a27c05d6d..014b5ee509a 100644
--- a/TriblerGUI/qt_resources/mainwindow.ui
+++ b/TriblerGUI/qt_resources/mainwindow.ui
@@ -7,7 +7,7 @@
0
0
875
- 768
+ 777
@@ -7982,8 +7982,8 @@ QTabBar::tab:selected {
0
0
- 673
- 341
+ 131
+ 260
@@ -11196,7 +11196,7 @@ QTabBar::tab:selected {
}
- 0
+ 1
@@ -11273,8 +11273,11 @@ QTabBar::tab:selected {
-
+
+ QAbstractItemView::NoSelection
+
- 8
+ 0
diff --git a/TriblerGUI/utilities.py b/TriblerGUI/utilities.py
index 49a06d1d839..9f3cfa92fc0 100644
--- a/TriblerGUI/utilities.py
+++ b/TriblerGUI/utilities.py
@@ -48,7 +48,7 @@ def timestamp_to_time(timestamp):
diff = today - discovered
if diff.days > 0 or today.day != discovered.day:
- return discovered.strftime('%d-%m-%Y')
+ return discovered.strftime('%d-%m-%Y %H:%M')
return discovered.strftime('Today %H:%M')
diff --git a/TriblerGUI/widgets/marketpage.py b/TriblerGUI/widgets/marketpage.py
index 7ba29e577f7..5ff8a82e3f5 100644
--- a/TriblerGUI/widgets/marketpage.py
+++ b/TriblerGUI/widgets/marketpage.py
@@ -214,6 +214,7 @@ def on_bid(self, bid):
def on_transaction_complete(self, transaction):
if transaction["mine"]:
+ transaction = transaction["tx"]
main_text = "Transaction with price %f %s and quantity %f %s completed." \
% (transaction["price"], transaction["price_type"],
transaction["quantity"], transaction["quantity_type"])
diff --git a/TriblerGUI/widgets/marketwalletspage.py b/TriblerGUI/widgets/marketwalletspage.py
index 4c2d254b7aa..c90133edd73 100644
--- a/TriblerGUI/widgets/marketwalletspage.py
+++ b/TriblerGUI/widgets/marketwalletspage.py
@@ -11,7 +11,7 @@
from TriblerGUI.dialogs.confirmationdialog import ConfirmationDialog
from TriblerGUI.tribler_action_menu import TriblerActionMenu
from TriblerGUI.tribler_request_manager import TriblerRequestManager
-from TriblerGUI.utilities import get_image_path
+from TriblerGUI.utilities import get_image_path, timestamp_to_time
class MarketWalletsPage(QWidget):
@@ -103,6 +103,7 @@ def initialize_wallet_info(self, wallet_id, pressed_button):
button.setChecked(False)
self.active_wallet = wallet_id
+ self.window().wallet_info_tabs.setCurrentIndex(0)
self.window().wallet_address_label.setText(self.wallets[wallet_id]['address'])
# Create a QR code of the wallet address
@@ -126,11 +127,11 @@ def initialize_wallet_info(self, wallet_id, pressed_button):
self.window().wallet_address_qr_label.setText("QR Code functionality not available!")
def load_transactions(self, wallet_id):
+ self.window().wallet_transactions_list.clear()
self.request_mgr = TriblerRequestManager()
self.request_mgr.perform_request("wallets/%s/transactions" % wallet_id, self.on_transactions)
def on_transactions(self, transactions):
- self.window().wallet_transactions_list.clear()
for transaction in transactions["transactions"]:
item = QTreeWidgetItem(self.window().wallet_transactions_list)
item.setText(0, "Sent" if transaction["outgoing"] else "Received")
@@ -139,7 +140,8 @@ def on_transactions(self, transactions):
item.setText(3, "%g %s" % (transaction["amount"], transaction["currency"]))
item.setText(4, "%g %s" % (transaction["fee_amount"], transaction["currency"]))
item.setText(5, transaction["id"])
- item.setText(6, transaction["timestamp"])
+ timestamp = timestamp_to_time(float(transaction["timestamp"])) if transaction["timestamp"] != "False" else "-"
+ item.setText(6, timestamp)
self.window().wallet_transactions_list.addTopLevelItem(item)
def on_add_wallet_clicked(self):