mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-06-08 07:02:44 -04:00
integration of TomP2P and basic use cases in dummy views tested
This commit is contained in:
parent
9a29004251
commit
6459184ce9
30 changed files with 1134 additions and 102 deletions
|
@ -21,11 +21,13 @@ git clone --recursive git://github.com/bitsquare/bitsquare
|
||||||
* Offer fee payment with a OP_RETURN tx and fees to miners
|
* Offer fee payment with a OP_RETURN tx and fees to miners
|
||||||
* Pay in to MS fund
|
* Pay in to MS fund
|
||||||
* Payout from MS fund
|
* Payout from MS fund
|
||||||
|
* TomP2P as messaging lib integrated and basic use cases in msg screen implemented: orderbook, add order, remove order, find peer, chat with peer
|
||||||
|
|
||||||
### Next steps:
|
### Next steps:
|
||||||
|
* Implement messaging with TomP2P for registration, orderbook and payment process
|
||||||
* Arbitrator integration
|
* Arbitrator integration
|
||||||
* Messaging system
|
|
||||||
* Other trade variants (Buy BTC taker, Sell BTC offerer, Sell BTC offerer)
|
* Other trade variants (Buy BTC taker, Sell BTC offerer, Sell BTC offerer)
|
||||||
|
* Verify registration and fee payments tx and get them from the blockchain
|
||||||
* ...
|
* ...
|
||||||
|
|
||||||
|
|
||||||
|
|
1
TODO.txt
1
TODO.txt
|
@ -1,5 +1,4 @@
|
||||||
- arbitration integration
|
- arbitration integration
|
||||||
- Messaging!
|
|
||||||
- settings
|
- settings
|
||||||
|
|
||||||
low prio:
|
low prio:
|
||||||
|
|
12
pom.xml
12
pom.xml
|
@ -59,6 +59,12 @@
|
||||||
<url>http://mvn-adamgent.googlecode.com/svn/maven/release</url>
|
<url>http://mvn-adamgent.googlecode.com/svn/maven/release</url>
|
||||||
<name>Adam Gent Maven Repository</name>
|
<name>Adam Gent Maven Repository</name>
|
||||||
</repository>
|
</repository>
|
||||||
|
|
||||||
|
<repository>
|
||||||
|
<id>tomp2p.net</id>
|
||||||
|
<url>http://tomp2p.net/dev/mvn/</url>
|
||||||
|
</repository>
|
||||||
|
|
||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
<!-- TODO Maven build not working yet... -->
|
<!-- TODO Maven build not working yet... -->
|
||||||
|
@ -170,6 +176,12 @@
|
||||||
<version>1.3</version>
|
<version>1.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.tomp2p</groupId>
|
||||||
|
<artifactId>TomP2P</artifactId>
|
||||||
|
<version>4.4</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<reporting>
|
<reporting>
|
||||||
|
|
|
@ -9,6 +9,7 @@ import io.bitsquare.btc.WalletFacade;
|
||||||
import io.bitsquare.di.BitSquareModule;
|
import io.bitsquare.di.BitSquareModule;
|
||||||
import io.bitsquare.di.GuiceFXMLLoader;
|
import io.bitsquare.di.GuiceFXMLLoader;
|
||||||
import io.bitsquare.gui.util.Localisation;
|
import io.bitsquare.gui.util.Localisation;
|
||||||
|
import io.bitsquare.msg.MessageFacade;
|
||||||
import io.bitsquare.settings.Settings;
|
import io.bitsquare.settings.Settings;
|
||||||
import io.bitsquare.storage.Storage;
|
import io.bitsquare.storage.Storage;
|
||||||
import io.bitsquare.user.Arbitrator;
|
import io.bitsquare.user.Arbitrator;
|
||||||
|
@ -28,9 +29,15 @@ public class BitSquare extends Application
|
||||||
{
|
{
|
||||||
private static final Logger log = LoggerFactory.getLogger(BitSquare.class);
|
private static final Logger log = LoggerFactory.getLogger(BitSquare.class);
|
||||||
private WalletFacade walletFacade;
|
private WalletFacade walletFacade;
|
||||||
|
private MessageFacade messageFacade;
|
||||||
|
|
||||||
public static void main(String[] args)
|
public static void main(String[] args)
|
||||||
{
|
{
|
||||||
|
if (args.length > 0)
|
||||||
|
WalletFacade.WALLET_PREFIX = args[0];
|
||||||
|
else
|
||||||
|
WalletFacade.WALLET_PREFIX = "bitsquare";
|
||||||
|
|
||||||
launch(args);
|
launch(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,6 +46,7 @@ public class BitSquare extends Application
|
||||||
{
|
{
|
||||||
final Injector injector = Guice.createInjector(new BitSquareModule());
|
final Injector injector = Guice.createInjector(new BitSquareModule());
|
||||||
walletFacade = injector.getInstance(WalletFacade.class);
|
walletFacade = injector.getInstance(WalletFacade.class);
|
||||||
|
messageFacade = injector.getInstance(MessageFacade.class);
|
||||||
|
|
||||||
// apply stored data
|
// apply stored data
|
||||||
final User user = injector.getInstance(User.class);
|
final User user = injector.getInstance(User.class);
|
||||||
|
@ -51,7 +59,7 @@ public class BitSquare extends Application
|
||||||
|
|
||||||
settings.updateFromStorage((Settings) storage.read(settings.getClass().getName()));
|
settings.updateFromStorage((Settings) storage.read(settings.getClass().getName()));
|
||||||
|
|
||||||
stage.setTitle("BitSquare");
|
stage.setTitle("BitSquare (" + WalletFacade.WALLET_PREFIX + ")");
|
||||||
|
|
||||||
GuiceFXMLLoader.setInjector(injector);
|
GuiceFXMLLoader.setInjector(injector);
|
||||||
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource("/io/bitsquare/gui/MainView.fxml"), Localisation.getResourceBundle());
|
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource("/io/bitsquare/gui/MainView.fxml"), Localisation.getResourceBundle());
|
||||||
|
@ -75,6 +83,7 @@ public class BitSquare extends Application
|
||||||
public void stop() throws Exception
|
public void stop() throws Exception
|
||||||
{
|
{
|
||||||
walletFacade.shutDown();
|
walletFacade.shutDown();
|
||||||
|
messageFacade.shutDown();
|
||||||
|
|
||||||
super.stop();
|
super.stop();
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,11 +36,13 @@ public class WalletFacade implements WalletEventListener
|
||||||
public static final String MAIN_NET = "MAIN_NET";
|
public static final String MAIN_NET = "MAIN_NET";
|
||||||
public static final String TEST_NET = "TEST_NET";
|
public static final String TEST_NET = "TEST_NET";
|
||||||
|
|
||||||
// for testing trade process between offerer and taker
|
public static String WALLET_PREFIX;
|
||||||
//public static final String WALLET_PREFIX = "offerer"; // offerer
|
|
||||||
public static final String WALLET_PREFIX = "taker"; // offerer
|
|
||||||
|
|
||||||
//public static final String WALLET_PREFIX = "bitsquare";
|
// for testing trade process between offerer and taker
|
||||||
|
//public static String WALLET_PREFIX = "offerer"; // offerer
|
||||||
|
//public static String WALLET_PREFIX = "taker"; // offerer
|
||||||
|
|
||||||
|
//public static String WALLET_PREFIX = "bitsquare";
|
||||||
|
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(WalletFacade.class);
|
private static final Logger log = LoggerFactory.getLogger(WalletFacade.class);
|
||||||
|
@ -105,14 +107,11 @@ public class WalletFacade implements WalletEventListener
|
||||||
|
|
||||||
wallet = walletAppKit.wallet();
|
wallet = walletAppKit.wallet();
|
||||||
|
|
||||||
// Don't make the user wait for confirmations for now, as the intention is they're sending it their own money!
|
//wallet.allowSpendingUnconfirmedTransactions();
|
||||||
wallet.allowSpendingUnconfirmedTransactions();
|
|
||||||
walletAppKit.peerGroup().setMaxConnections(20);
|
walletAppKit.peerGroup().setMaxConnections(20);
|
||||||
|
|
||||||
wallet.addEventListener(this);
|
wallet.addEventListener(this);
|
||||||
|
|
||||||
log.info(wallet.toString());
|
|
||||||
|
|
||||||
// testTradeProcessDepositTx();
|
// testTradeProcessDepositTx();
|
||||||
// testTradeProcessPayOutTx();
|
// testTradeProcessPayOutTx();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,4 +3,6 @@ package io.bitsquare.gui;
|
||||||
public interface ChildController
|
public interface ChildController
|
||||||
{
|
{
|
||||||
void setNavigationController(NavigationController navigationController);
|
void setNavigationController(NavigationController navigationController);
|
||||||
|
|
||||||
|
void cleanup();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import io.bitsquare.gui.market.MarketController;
|
||||||
import io.bitsquare.gui.setup.SetupController;
|
import io.bitsquare.gui.setup.SetupController;
|
||||||
import io.bitsquare.gui.util.Icons;
|
import io.bitsquare.gui.util.Icons;
|
||||||
import io.bitsquare.gui.util.Localisation;
|
import io.bitsquare.gui.util.Localisation;
|
||||||
|
import io.bitsquare.msg.MessageFacade;
|
||||||
import io.bitsquare.trade.Direction;
|
import io.bitsquare.trade.Direction;
|
||||||
import io.bitsquare.user.User;
|
import io.bitsquare.user.User;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
|
@ -39,6 +40,7 @@ public class MainController implements Initializable, NavigationController, Wall
|
||||||
|
|
||||||
private User user;
|
private User user;
|
||||||
private WalletFacade walletFacade;
|
private WalletFacade walletFacade;
|
||||||
|
private MessageFacade messageFacade;
|
||||||
private ChildController childController;
|
private ChildController childController;
|
||||||
private ToggleGroup toggleGroup;
|
private ToggleGroup toggleGroup;
|
||||||
private ToggleButton prevToggleButton;
|
private ToggleButton prevToggleButton;
|
||||||
|
@ -62,10 +64,11 @@ public class MainController implements Initializable, NavigationController, Wall
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public MainController(User user, WalletFacade walletFacade)
|
public MainController(User user, WalletFacade walletFacade, MessageFacade messageFacade)
|
||||||
{
|
{
|
||||||
this.user = user;
|
this.user = user;
|
||||||
this.walletFacade = walletFacade;
|
this.walletFacade = walletFacade;
|
||||||
|
this.messageFacade = messageFacade;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -80,6 +83,8 @@ public class MainController implements Initializable, NavigationController, Wall
|
||||||
networkSyncPane.setSpacing(10);
|
networkSyncPane.setSpacing(10);
|
||||||
networkSyncPane.setPrefHeight(20);
|
networkSyncPane.setPrefHeight(20);
|
||||||
|
|
||||||
|
messageFacade.init();
|
||||||
|
|
||||||
walletFacade.addDownloadListener(this);
|
walletFacade.addDownloadListener(this);
|
||||||
walletFacade.initWallet();
|
walletFacade.initWallet();
|
||||||
|
|
||||||
|
@ -116,10 +121,8 @@ public class MainController implements Initializable, NavigationController, Wall
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (childController instanceof MarketController)
|
if (childController != null)
|
||||||
{
|
childController.cleanup();
|
||||||
((MarketController) childController).cleanup();
|
|
||||||
}
|
|
||||||
|
|
||||||
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(fxmlView), Localisation.getResourceBundle());
|
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(fxmlView), Localisation.getResourceBundle());
|
||||||
try
|
try
|
||||||
|
@ -184,14 +187,15 @@ public class MainController implements Initializable, NavigationController, Wall
|
||||||
addNavButton(leftNavPane, "Orders", Icons.ORDERS, Icons.ORDERS, NavigationController.ORDERS);
|
addNavButton(leftNavPane, "Orders", Icons.ORDERS, Icons.ORDERS, NavigationController.ORDERS);
|
||||||
addNavButton(leftNavPane, "History", Icons.HISTORY, Icons.HISTORY, NavigationController.HISTORY);
|
addNavButton(leftNavPane, "History", Icons.HISTORY, Icons.HISTORY, NavigationController.HISTORY);
|
||||||
addNavButton(leftNavPane, "Funds", Icons.FUNDS, Icons.FUNDS, NavigationController.FUNDS);
|
addNavButton(leftNavPane, "Funds", Icons.FUNDS, Icons.FUNDS, NavigationController.FUNDS);
|
||||||
addNavButton(leftNavPane, "Message", Icons.MSG, Icons.MSG, NavigationController.MSG);
|
ToggleButton msgButton = addNavButton(leftNavPane, "Message", Icons.MSG, Icons.MSG, NavigationController.MSG);
|
||||||
addBalanceInfo(rightNavPane);
|
addBalanceInfo(rightNavPane);
|
||||||
addAccountComboBox(rightNavPane);
|
addAccountComboBox(rightNavPane);
|
||||||
|
|
||||||
addNavButton(rightNavPane, "Settings", Icons.SETTINGS, Icons.SETTINGS, NavigationController.SETTINGS);
|
addNavButton(rightNavPane, "Settings", Icons.SETTINGS, Icons.SETTINGS, NavigationController.SETTINGS);
|
||||||
|
|
||||||
sellButton.fire();
|
//sellButton.fire();
|
||||||
//homeButton.fire();
|
//homeButton.fire();
|
||||||
|
msgButton.fire();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ToggleButton addNavButton(Pane parent, String title, String iconId, String iconIdActivated, String navTarget)
|
private ToggleButton addNavButton(Pane parent, String title, String iconId, String iconIdActivated, String navTarget)
|
||||||
|
|
|
@ -66,6 +66,12 @@ public class FundsController implements Initializable, ChildController
|
||||||
balanceLabel.setText(BtcFormatter.formatSatoshis(walletFacade.getBalance(), false));
|
balanceLabel.setText(BtcFormatter.formatSatoshis(walletFacade.getBalance(), false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cleanup()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,5 +24,11 @@ public class HistoryController implements Initializable, ChildController
|
||||||
{
|
{
|
||||||
this.navigationController = navigationController;
|
this.navigationController = navigationController;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cleanup()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,5 +28,11 @@ public class HomeController implements Initializable, ChildController
|
||||||
this.navigationController = navigationController;
|
this.navigationController = navigationController;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cleanup()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,11 +93,7 @@ public class MarketController implements Initializable, NavigationController, Ch
|
||||||
this.navigationController = navigationController;
|
this.navigationController = navigationController;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Public methods
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
public void cleanup()
|
public void cleanup()
|
||||||
{
|
{
|
||||||
if (orderBookController != null)
|
if (orderBookController != null)
|
||||||
|
|
|
@ -114,6 +114,12 @@ public class CreateOfferController implements Initializable, ChildController, Wa
|
||||||
this.navigationController = navigationController;
|
this.navigationController = navigationController;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cleanup()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Interface implementation: WalletFacade.WalletListener
|
// Interface implementation: WalletFacade.WalletListener
|
||||||
|
|
|
@ -138,6 +138,15 @@ public class OrderBookController implements Initializable, ChildController
|
||||||
this.navigationController = navigationController;
|
this.navigationController = navigationController;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cleanup()
|
||||||
|
{
|
||||||
|
orderBookTable.setItems(null);
|
||||||
|
orderBookTable.getSortOrder().clear();
|
||||||
|
offerList.comparatorProperty().unbind();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setDirection(Direction direction)
|
public void setDirection(Direction direction)
|
||||||
{
|
{
|
||||||
orderBookTable.getSelectionModel().clearSelection();
|
orderBookTable.getSelectionModel().clearSelection();
|
||||||
|
@ -145,12 +154,6 @@ public class OrderBookController implements Initializable, ChildController
|
||||||
orderBookFilter.setDirection(direction);
|
orderBookFilter.setDirection(direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cleanup()
|
|
||||||
{
|
|
||||||
orderBookTable.setItems(null);
|
|
||||||
orderBookTable.getSortOrder().clear();
|
|
||||||
offerList.comparatorProperty().unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void openTradeTab(OrderBookListItem orderBookListItem)
|
private void openTradeTab(OrderBookListItem orderBookListItem)
|
||||||
{
|
{
|
||||||
|
|
|
@ -122,6 +122,12 @@ public class TradeController implements Initializable, ChildController, WalletFa
|
||||||
this.navigationController = navigationController;
|
this.navigationController = navigationController;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cleanup()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Interface implementation: WalletFacade.WalletListener
|
// Interface implementation: WalletFacade.WalletListener
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
package io.bitsquare.gui.msg;
|
|
||||||
|
|
||||||
|
|
||||||
import java.util.concurrent.*;
|
|
||||||
|
|
||||||
public class MockDelay
|
|
||||||
{
|
|
||||||
public String waitForMsg(String expectedMsg)
|
|
||||||
{
|
|
||||||
ExecutorService executor = Executors.newSingleThreadExecutor();
|
|
||||||
Future<String> future = executor.submit(new Task(expectedMsg));
|
|
||||||
// max timeout 5 sec
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return future.get(5, TimeUnit.SECONDS);
|
|
||||||
} catch (InterruptedException | TimeoutException | ExecutionException e)
|
|
||||||
{
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
executor.shutdownNow();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Task implements Callable<String>
|
|
||||||
{
|
|
||||||
private String expectedMsg;
|
|
||||||
|
|
||||||
Task(String expectedMsg)
|
|
||||||
{
|
|
||||||
this.expectedMsg = expectedMsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String call() throws Exception
|
|
||||||
{
|
|
||||||
Thread.sleep(1000); // 1 seconds pause
|
|
||||||
return expectedMsg;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,26 +1,346 @@
|
||||||
package io.bitsquare.gui.msg;
|
package io.bitsquare.gui.msg;
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import io.bitsquare.btc.WalletFacade;
|
||||||
import io.bitsquare.gui.ChildController;
|
import io.bitsquare.gui.ChildController;
|
||||||
import io.bitsquare.gui.NavigationController;
|
import io.bitsquare.gui.NavigationController;
|
||||||
|
import io.bitsquare.msg.MessageFacade;
|
||||||
|
import io.bitsquare.msg.MessageListener;
|
||||||
|
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||||
|
import javafx.collections.FXCollections;
|
||||||
|
import javafx.collections.ObservableList;
|
||||||
|
import javafx.event.ActionEvent;
|
||||||
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.Initializable;
|
import javafx.fxml.Initializable;
|
||||||
|
import javafx.scene.control.*;
|
||||||
|
import javafx.util.Callback;
|
||||||
|
import net.tomp2p.peers.Number160;
|
||||||
|
import net.tomp2p.storage.Data;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
public class MsgController implements Initializable, ChildController
|
public class MsgController implements Initializable, ChildController, MessageListener
|
||||||
{
|
{
|
||||||
private NavigationController navigationController;
|
private static final Logger log = LoggerFactory.getLogger(MsgController.class);
|
||||||
|
|
||||||
|
private MessageFacade messageFacade;
|
||||||
|
private String selectedCurrency;
|
||||||
|
private ObservableList<OfferListItem> offerList = FXCollections.observableArrayList();
|
||||||
|
private int selectedIndex;
|
||||||
|
private String myID, otherID;
|
||||||
|
private boolean pingPending;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
public ComboBox currencyComboBox;
|
||||||
|
@FXML
|
||||||
|
public Button sendButton;
|
||||||
|
@FXML
|
||||||
|
public TextArea chatTextArea;
|
||||||
|
@FXML
|
||||||
|
public TextField chatInputField, peerIDTextField, currencyTextField, offerDataTextField;
|
||||||
|
@FXML
|
||||||
|
public TableView offerTable;
|
||||||
|
@FXML
|
||||||
|
public TableColumn<String, OfferListItem> connectToPeerColumn, removeOfferColumn, offerColumn;
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Constructor
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public MsgController(MessageFacade messageFacade)
|
||||||
|
{
|
||||||
|
this.messageFacade = messageFacade;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Interface implementation: Initializable
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(URL url, ResourceBundle rb)
|
public void initialize(URL url, ResourceBundle rb)
|
||||||
{
|
{
|
||||||
|
myID = WalletFacade.WALLET_PREFIX;
|
||||||
|
otherID = WalletFacade.WALLET_PREFIX.equals("taker") ? "offerer" : "taker";
|
||||||
|
|
||||||
|
messageFacade.addMessageListener(this);
|
||||||
|
|
||||||
|
peerIDTextField.setText(myID);
|
||||||
|
currencyTextField.setText("EUR");
|
||||||
|
offerDataTextField.setText(myID + " serialized offer object");
|
||||||
|
|
||||||
|
selectedCurrency = currencyTextField.getText();
|
||||||
|
|
||||||
|
currencyComboBox.setItems(FXCollections.observableArrayList(new ArrayList<>(Arrays.asList("EUR", "USD", "CHF"))));
|
||||||
|
currencyComboBox.getSelectionModel().select(0);
|
||||||
|
|
||||||
|
setupConnectToPeerOfferColumn();
|
||||||
|
setupRemoveOfferColumn();
|
||||||
|
offerTable.setItems(offerList);
|
||||||
|
offerTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Interface implementation: MessageListener
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMessage(Object message)
|
||||||
|
{
|
||||||
|
sendButton.setDisable(!messageFacade.isOtherPeerDefined());
|
||||||
|
|
||||||
|
if (message instanceof String)
|
||||||
|
chatTextArea.appendText("\n" + otherID + ": " + message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPing()
|
||||||
|
{
|
||||||
|
sendChatMsg(MessageFacade.PONG);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onOfferPublished(boolean success)
|
||||||
|
{
|
||||||
|
if (success)
|
||||||
|
getOffers();
|
||||||
|
else
|
||||||
|
log.warn("onOfferPublished returned false");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onOffersReceived(Map<Number160, Data> dataMap, boolean success)
|
||||||
|
{
|
||||||
|
if (success && dataMap != null)
|
||||||
|
{
|
||||||
|
offerList.clear();
|
||||||
|
for (Data offerData : dataMap.values())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Object offerDataObject = offerData.getObject();
|
||||||
|
if (offerDataObject instanceof OfferListItem && offerDataObject != null)
|
||||||
|
offerList.add((OfferListItem) offerDataObject);
|
||||||
|
} catch (ClassNotFoundException | IOException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
offerList.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onOfferRemoved(boolean success)
|
||||||
|
{
|
||||||
|
if (success)
|
||||||
|
getOffers();
|
||||||
|
else
|
||||||
|
log.warn("onOfferRemoved failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResponseFromSend(Object response)
|
||||||
|
{
|
||||||
|
String msg = (response instanceof String) ? (String) response : null;
|
||||||
|
if (msg != null)
|
||||||
|
{
|
||||||
|
chatTextArea.appendText("\n" + otherID + ": " + msg);
|
||||||
|
offerTable.getSelectionModel().select(selectedIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSendFailed()
|
||||||
|
{
|
||||||
|
offerTable.getSelectionModel().clearSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPeerFound()
|
||||||
|
{
|
||||||
|
sendButton.setDisable(!messageFacade.isOtherPeerDefined());
|
||||||
|
if (pingPending)
|
||||||
|
sendChatMsg(MessageFacade.PING);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Interface implementation: ChildController
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setNavigationController(NavigationController navigationController)
|
public void setNavigationController(NavigationController navigationController)
|
||||||
{
|
{
|
||||||
this.navigationController = navigationController;
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cleanup()
|
||||||
|
{
|
||||||
|
messageFacade.removeMessageListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// GUI Event handlers
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
public void publishOffer(ActionEvent actionEvent)
|
||||||
|
{
|
||||||
|
OfferListItem offerListItem = new OfferListItem(offerDataTextField.getText(), messageFacade.getPubKeyAsHex(), currencyTextField.getText());
|
||||||
|
try
|
||||||
|
{
|
||||||
|
messageFacade.publishOffer(currencyTextField.getText(), offerListItem);
|
||||||
|
} catch (IOException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
public void selectCurrency(ActionEvent actionEvent)
|
||||||
|
{
|
||||||
|
selectedCurrency = currencyComboBox.getSelectionModel().getSelectedItem().toString();
|
||||||
|
getOffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
public void sendChatMsg(ActionEvent actionEvent)
|
||||||
|
{
|
||||||
|
sendChatMsg(chatInputField.getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Private Methods
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
private void inviteForChat(OfferListItem item, int index)
|
||||||
|
{
|
||||||
|
selectedIndex = index;
|
||||||
|
messageFacade.findPeer(item.getPubKey());
|
||||||
|
pingPending = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendChatMsg(String msg)
|
||||||
|
{
|
||||||
|
messageFacade.sendMessage(msg);
|
||||||
|
|
||||||
|
chatTextArea.appendText("\n" + myID + ": " + msg);
|
||||||
|
chatInputField.setText("");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getOffers()
|
||||||
|
{
|
||||||
|
messageFacade.getOffers(selectedCurrency);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeOffer(OfferListItem offer)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
messageFacade.removeOffer(currencyTextField.getText(), offer);
|
||||||
|
} catch (IOException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Columns
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
private void setupRemoveOfferColumn()
|
||||||
|
{
|
||||||
|
removeOfferColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper(offer.getValue()));
|
||||||
|
removeOfferColumn.setCellFactory(new Callback<TableColumn<String, OfferListItem>, TableCell<String, OfferListItem>>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public TableCell<String, OfferListItem> call(TableColumn<String, OfferListItem> directionColumn)
|
||||||
|
{
|
||||||
|
return new TableCell<String, OfferListItem>()
|
||||||
|
{
|
||||||
|
final Button button = new Button();
|
||||||
|
|
||||||
|
{
|
||||||
|
button.setMinWidth(70);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateItem(final OfferListItem item, boolean empty)
|
||||||
|
{
|
||||||
|
super.updateItem(item, empty);
|
||||||
|
|
||||||
|
if (item != null)
|
||||||
|
{
|
||||||
|
button.setText("Remove");
|
||||||
|
setGraphic(button);
|
||||||
|
|
||||||
|
button.setOnAction(event -> removeOffer(item));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setGraphic(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupConnectToPeerOfferColumn()
|
||||||
|
{
|
||||||
|
connectToPeerColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper(offer.getValue()));
|
||||||
|
connectToPeerColumn.setCellFactory(new Callback<TableColumn<String, OfferListItem>, TableCell<String, OfferListItem>>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public TableCell<String, OfferListItem> call(TableColumn<String, OfferListItem> directionColumn)
|
||||||
|
{
|
||||||
|
return new TableCell<String, OfferListItem>()
|
||||||
|
{
|
||||||
|
final Button button = new Button();
|
||||||
|
|
||||||
|
{
|
||||||
|
button.setMinWidth(70);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateItem(OfferListItem item, boolean empty)
|
||||||
|
{
|
||||||
|
super.updateItem(item, empty);
|
||||||
|
|
||||||
|
if (item != null)
|
||||||
|
{
|
||||||
|
button.setText("Chat");
|
||||||
|
setGraphic(button);
|
||||||
|
|
||||||
|
|
||||||
|
button.setOnAction(event -> inviteForChat(item, getIndex()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setGraphic(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,80 @@
|
||||||
<?import javafx.scene.control.Label?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<?import javafx.scene.layout.Pane?>
|
|
||||||
<Pane fx:controller="io.bitsquare.gui.msg.MsgController"
|
<?import javafx.scene.control.*?>
|
||||||
xmlns:fx="http://javafx.com/fxml">
|
<?import javafx.scene.control.cell.PropertyValueFactory?>
|
||||||
<Label text="Msg"/>
|
<?import javafx.scene.layout.*?>
|
||||||
</Pane>
|
<?import javafx.scene.text.Font?>
|
||||||
|
<AnchorPane fx:controller="io.bitsquare.gui.msg.MsgController" AnchorPane.bottomAnchor="0" AnchorPane.leftAnchor="0" AnchorPane.rightAnchor="0"
|
||||||
|
AnchorPane.topAnchor="0" xmlns="http://javafx.com/javafx/8"
|
||||||
|
xmlns:fx="http://javafx.com/fxml/1">
|
||||||
|
<children>
|
||||||
|
|
||||||
|
<Label text="Offer list" AnchorPane.leftAnchor="10" AnchorPane.topAnchor="15.0">
|
||||||
|
<font>
|
||||||
|
<Font name="System Bold" size="18.0"/>
|
||||||
|
</font>
|
||||||
|
</Label>
|
||||||
|
<ComboBox fx:id="currencyComboBox" onAction="#selectCurrency" prefWidth="100" AnchorPane.rightAnchor="405" AnchorPane.topAnchor="10.0"/>
|
||||||
|
<TableView fx:id="offerTable" prefHeight="200.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="405"
|
||||||
|
AnchorPane.topAnchor="40.0">
|
||||||
|
<columns>
|
||||||
|
<TableColumn text="Offer" fx:id="offerColumn" minWidth="120">
|
||||||
|
<cellValueFactory>
|
||||||
|
<PropertyValueFactory property="offer"/>
|
||||||
|
</cellValueFactory>
|
||||||
|
</TableColumn>
|
||||||
|
<TableColumn text="Peer PubKey" fx:id="pubKeyColumn" minWidth="80" prefWidth="80">
|
||||||
|
<cellValueFactory>
|
||||||
|
<PropertyValueFactory property="pubKey"/>
|
||||||
|
</cellValueFactory>
|
||||||
|
</TableColumn>
|
||||||
|
<TableColumn text="" fx:id="removeOfferColumn" minWidth="80" sortable="false"/>
|
||||||
|
<TableColumn text="" fx:id="connectToPeerColumn" minWidth="80" sortable="false"/>
|
||||||
|
</columns>
|
||||||
|
</TableView>
|
||||||
|
|
||||||
|
|
||||||
|
<Label text="Chat with peer" AnchorPane.bottomAnchor="210.0" AnchorPane.leftAnchor="10.0">
|
||||||
|
<font>
|
||||||
|
<Font name="System Bold" size="18.0"/>
|
||||||
|
</font>
|
||||||
|
</Label>
|
||||||
|
<TextArea fx:id="chatTextArea" editable="false" prefHeight="160.0" AnchorPane.bottomAnchor="45.0" AnchorPane.leftAnchor="10.0"
|
||||||
|
AnchorPane.rightAnchor="10.0"/>
|
||||||
|
<TextField fx:id="chatInputField" AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="120.0"/>
|
||||||
|
<Button fx:id="sendButton" onAction="#sendChatMsg" disable="true" defaultButton="true" prefWidth="100.0" text="Send" AnchorPane.bottomAnchor="10.0"
|
||||||
|
AnchorPane.rightAnchor="10"/>
|
||||||
|
|
||||||
|
|
||||||
|
<GridPane hgap="5.0" prefWidth="385.0" vgap="5.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="40.0">
|
||||||
|
<children>
|
||||||
|
<Label layoutX="418.0" text="Add new Offer" AnchorPane.topAnchor="10.0" GridPane.columnSpan="2" GridPane.halignment="LEFT"
|
||||||
|
GridPane.rowIndex="0">
|
||||||
|
<font>
|
||||||
|
<Font name="System Bold" size="18.0"/>
|
||||||
|
</font>
|
||||||
|
</Label>
|
||||||
|
<Label text="Peer ID:" GridPane.rowIndex="1"/>
|
||||||
|
<Label text="Currency:" GridPane.rowIndex="2"/>
|
||||||
|
<Label text="Offer data:" GridPane.rowIndex="3"/>
|
||||||
|
<TextField fx:id="peerIDTextField" GridPane.columnIndex="1" GridPane.rowIndex="1"/>
|
||||||
|
<TextField fx:id="currencyTextField" GridPane.columnIndex="1" GridPane.rowIndex="2"/>
|
||||||
|
<TextField fx:id="offerDataTextField" GridPane.columnIndex="1" GridPane.rowIndex="3"/>
|
||||||
|
<Button onAction="#publishOffer" text="Add Offer" GridPane.columnIndex="1" GridPane.rowIndex="4"/>
|
||||||
|
</children>
|
||||||
|
|
||||||
|
<columnConstraints>
|
||||||
|
<ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" minWidth="10.0"/>
|
||||||
|
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0"/>
|
||||||
|
</columnConstraints>
|
||||||
|
<rowConstraints>
|
||||||
|
<RowConstraints minHeight="10.0" vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints minHeight="10.0" vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints minHeight="10.0" vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints minHeight="10.0" vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints minHeight="10.0" vgrow="ALWAYS"/>
|
||||||
|
</rowConstraints>
|
||||||
|
</GridPane>
|
||||||
|
|
||||||
|
</children>
|
||||||
|
</AnchorPane>
|
||||||
|
|
40
src/main/java/io/bitsquare/gui/msg/OfferListItem.java
Normal file
40
src/main/java/io/bitsquare/gui/msg/OfferListItem.java
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
package io.bitsquare.gui.msg;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper for observable properties used by orderbook table view
|
||||||
|
*/
|
||||||
|
public class OfferListItem implements Serializable
|
||||||
|
{
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 7914481258209700131L;
|
||||||
|
|
||||||
|
private String _offer;
|
||||||
|
private String pubKey;
|
||||||
|
private String currency;
|
||||||
|
|
||||||
|
|
||||||
|
public OfferListItem(String offer, String pubKey, String currency)
|
||||||
|
{
|
||||||
|
_offer = offer;
|
||||||
|
this.pubKey = pubKey;
|
||||||
|
this.currency = currency;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOffer()
|
||||||
|
{
|
||||||
|
return _offer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPubKey()
|
||||||
|
{
|
||||||
|
return pubKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCurrency()
|
||||||
|
{
|
||||||
|
return currency;
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,5 +26,11 @@ public class OrdersController implements Initializable, ChildController
|
||||||
this.navigationController = navigationController;
|
this.navigationController = navigationController;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cleanup()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,5 +39,11 @@ public class SettingsController implements Initializable, ChildController
|
||||||
this.navigationController = navigationController;
|
this.navigationController = navigationController;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cleanup()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ import io.bitsquare.gui.util.FormBuilder;
|
||||||
import io.bitsquare.gui.util.Localisation;
|
import io.bitsquare.gui.util.Localisation;
|
||||||
import io.bitsquare.gui.util.Popups;
|
import io.bitsquare.gui.util.Popups;
|
||||||
import io.bitsquare.gui.util.Verification;
|
import io.bitsquare.gui.util.Verification;
|
||||||
|
import io.bitsquare.msg.MessageFacade;
|
||||||
import io.bitsquare.storage.Storage;
|
import io.bitsquare.storage.Storage;
|
||||||
import io.bitsquare.user.User;
|
import io.bitsquare.user.User;
|
||||||
import io.bitsquare.util.Utils;
|
import io.bitsquare.util.Utils;
|
||||||
|
@ -43,6 +44,7 @@ public class SetupController implements Initializable, ChildController, WalletFa
|
||||||
|
|
||||||
private final User user;
|
private final User user;
|
||||||
private final WalletFacade walletFacade;
|
private final WalletFacade walletFacade;
|
||||||
|
private MessageFacade messageFacade;
|
||||||
private final Storage storage;
|
private final Storage storage;
|
||||||
private final List<ProcessStepItem> processStepItems = new ArrayList<>();
|
private final List<ProcessStepItem> processStepItems = new ArrayList<>();
|
||||||
private NavigationController navigationController;
|
private NavigationController navigationController;
|
||||||
|
@ -71,10 +73,11 @@ public class SetupController implements Initializable, ChildController, WalletFa
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public SetupController(User user, WalletFacade walletFacade, Storage storage)
|
public SetupController(User user, WalletFacade walletFacade, MessageFacade messageFacade, Storage storage)
|
||||||
{
|
{
|
||||||
this.user = user;
|
this.user = user;
|
||||||
this.walletFacade = walletFacade;
|
this.walletFacade = walletFacade;
|
||||||
|
this.messageFacade = messageFacade;
|
||||||
this.storage = storage;
|
this.storage = storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,6 +121,11 @@ public class SetupController implements Initializable, ChildController, WalletFa
|
||||||
this.navigationController = navigationController;
|
this.navigationController = navigationController;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cleanup()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Interface implementation: WalletFacade.WalletListener
|
// Interface implementation: WalletFacade.WalletListener
|
||||||
|
@ -305,6 +313,7 @@ public class SetupController implements Initializable, ChildController, WalletFa
|
||||||
walletFacade.sendRegistrationTx(user.getStringifiedBankAccounts());
|
walletFacade.sendRegistrationTx(user.getStringifiedBankAccounts());
|
||||||
user.setAccountID(walletFacade.getAccountRegistrationAddress().toString());
|
user.setAccountID(walletFacade.getAccountRegistrationAddress().toString());
|
||||||
user.setMessageID(walletFacade.getAccountRegistrationPubKey());
|
user.setMessageID(walletFacade.getAccountRegistrationPubKey());
|
||||||
|
//user.setMessageID(messageFacade.getPubKey());
|
||||||
|
|
||||||
storage.write(user.getClass().getName(), user);
|
storage.write(user.getClass().getName(), user);
|
||||||
processStepBar.next();
|
processStepBar.next();
|
||||||
|
|
24
src/main/java/io/bitsquare/msg/BootstrapMasterPeer.java
Executable file
24
src/main/java/io/bitsquare/msg/BootstrapMasterPeer.java
Executable file
|
@ -0,0 +1,24 @@
|
||||||
|
package io.bitsquare.msg;
|
||||||
|
|
||||||
|
import net.tomp2p.p2p.Peer;
|
||||||
|
import net.tomp2p.p2p.PeerMaker;
|
||||||
|
import net.tomp2p.peers.Number160;
|
||||||
|
|
||||||
|
public class BootstrapMasterPeer
|
||||||
|
{
|
||||||
|
private static Peer masterPeer = null;
|
||||||
|
public static Number160 ID = Number160.createHash(1);
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception
|
||||||
|
{
|
||||||
|
INSTANCE(5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Peer INSTANCE(int port) throws Exception
|
||||||
|
{
|
||||||
|
if (masterPeer == null)
|
||||||
|
masterPeer = new PeerMaker(ID).setPorts(port).makeAndListen();
|
||||||
|
|
||||||
|
return masterPeer;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,30 +1,398 @@
|
||||||
package io.bitsquare.msg;
|
package io.bitsquare.msg;
|
||||||
|
|
||||||
|
import com.google.bitcoin.core.Utils;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import io.bitsquare.btc.WalletFacade;
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import net.tomp2p.connection.Bindings;
|
||||||
|
import net.tomp2p.connection.PeerConnection;
|
||||||
|
import net.tomp2p.futures.*;
|
||||||
|
import net.tomp2p.p2p.Peer;
|
||||||
|
import net.tomp2p.p2p.PeerMaker;
|
||||||
|
import net.tomp2p.peers.Number160;
|
||||||
|
import net.tomp2p.peers.PeerAddress;
|
||||||
|
import net.tomp2p.rpc.ObjectDataReply;
|
||||||
|
import net.tomp2p.storage.Data;
|
||||||
|
import net.tomp2p.storage.StorageDisk;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.KeyPair;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* That facade delivers messaging functionality from an external library -> to be defined...
|
* That facade delivers messaging functionality from the TomP2P library
|
||||||
* The external library codebase must not be used outside that facade.
|
* The TomP2P library codebase shall not be used outside that facade.
|
||||||
* That way a change of the library will only affect that class.
|
* That way a change of the library will only affect that class.
|
||||||
*/
|
*/
|
||||||
public class MessageFacade
|
public class MessageFacade
|
||||||
{
|
{
|
||||||
private static final Logger log = LoggerFactory.getLogger(MessageFacade.class);
|
private static final Logger log = LoggerFactory.getLogger(MessageFacade.class);
|
||||||
|
|
||||||
public void broadcast(Message message)
|
public static final String PING = "ping";
|
||||||
|
public static final String PONG = "pong";
|
||||||
|
private static final int MASTER_PEER_PORT = 5000;
|
||||||
|
private static String MASTER_PEER_IP = "127.0.0.1";
|
||||||
|
|
||||||
|
private Peer myPeerInstance;
|
||||||
|
private int port;
|
||||||
|
private KeyPair keyPair;
|
||||||
|
private Peer masterPeer;
|
||||||
|
private PeerAddress otherPeerAddress;
|
||||||
|
private PeerConnection peerConnection;
|
||||||
|
private List<MessageListener> messageListeners = new ArrayList<>();
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Constructor
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public MessageFacade()
|
||||||
{
|
{
|
||||||
log.info(message.toString());
|
try
|
||||||
|
{
|
||||||
|
masterPeer = BootstrapMasterPeer.INSTANCE(MASTER_PEER_PORT);
|
||||||
|
} catch (Exception e)
|
||||||
|
{
|
||||||
|
if (masterPeer != null)
|
||||||
|
masterPeer.shutdown();
|
||||||
|
log.info("masterPeer already instantiated by another app. " + e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void send(Message message, String receiverPubKey)
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Public Methods
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public void init()
|
||||||
{
|
{
|
||||||
log.info(message.toString() + "/" + receiverPubKey);
|
String keyName = WalletFacade.WALLET_PREFIX;
|
||||||
|
port = Bindings.MAX_PORT - Math.abs(new Random().nextInt()) % (Bindings.MAX_PORT - Bindings.MIN_DYN_PORT);
|
||||||
|
if (WalletFacade.WALLET_PREFIX.equals("taker"))
|
||||||
|
port = 4501;
|
||||||
|
else if (WalletFacade.WALLET_PREFIX.equals("offerer"))
|
||||||
|
port = 4500;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
createMyPeerInstance(keyName, port);
|
||||||
|
setupStorage();
|
||||||
|
saveMyAddressToDHT();
|
||||||
|
setupReplyHandler();
|
||||||
|
} catch (IOException e)
|
||||||
|
{
|
||||||
|
shutDown();
|
||||||
|
log.error("Error at setup peer" + e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerListener(String listenerPubKey)
|
//log.info("myPeerInstance knows: " + myPeerInstance.getPeerBean().getPeerMap().getAll());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void shutDown()
|
||||||
{
|
{
|
||||||
log.info(listenerPubKey);
|
if (peerConnection != null)
|
||||||
|
peerConnection.close();
|
||||||
|
|
||||||
|
if (myPeerInstance != null)
|
||||||
|
myPeerInstance.shutdown();
|
||||||
|
|
||||||
|
if (masterPeer != null)
|
||||||
|
masterPeer.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Publish offer
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//TODO use Offer and do proper serialisation here
|
||||||
|
public void publishOffer(String currency, Object offerObject) throws IOException
|
||||||
|
{
|
||||||
|
Number160 locationKey = Number160.createHash(currency);
|
||||||
|
Data offerData = new Data(offerObject);
|
||||||
|
offerData.setTTLSeconds(5);
|
||||||
|
FutureDHT putFuture = myPeerInstance.add(locationKey).setData(offerData).start();
|
||||||
|
putFuture.addListener(new BaseFutureAdapter<BaseFuture>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void operationComplete(BaseFuture future) throws Exception
|
||||||
|
{
|
||||||
|
Platform.runLater(() -> onOfferPublished(future.isSuccess()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onOfferPublished(boolean success)
|
||||||
|
{
|
||||||
|
for (MessageListener messageListener : messageListeners)
|
||||||
|
messageListener.onOfferPublished(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Get offers
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public void getOffers(String currency)
|
||||||
|
{
|
||||||
|
Number160 locationKey = Number160.createHash(currency);
|
||||||
|
final FutureDHT getOffersFuture = myPeerInstance.get(locationKey).setAll().start();
|
||||||
|
getOffersFuture.addListener(new BaseFutureAdapter<BaseFuture>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void operationComplete(BaseFuture future) throws Exception
|
||||||
|
{
|
||||||
|
final Map<Number160, Data> dataMap = getOffersFuture.getDataMap();
|
||||||
|
Platform.runLater(() -> onOffersReceived(dataMap, future.isSuccess()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onOffersReceived(Map<Number160, Data> dataMap, boolean success)
|
||||||
|
{
|
||||||
|
for (MessageListener messageListener : messageListeners)
|
||||||
|
messageListener.onOffersReceived(dataMap, success);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Remove offer
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public void removeOffer(String currency, Object offerObject) throws IOException
|
||||||
|
{
|
||||||
|
Data offerData = new Data(offerObject);
|
||||||
|
Number160 locationKey = Number160.createHash(currency);
|
||||||
|
Number160 contentKey = offerData.getHash();
|
||||||
|
FutureDHT putFuture = myPeerInstance.remove(locationKey).setContentKey(contentKey).start();
|
||||||
|
putFuture.addListener(new BaseFutureAdapter<BaseFuture>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void operationComplete(BaseFuture future) throws Exception
|
||||||
|
{
|
||||||
|
Platform.runLater(() -> onOfferRemoved(future.isSuccess()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onOfferRemoved(boolean success)
|
||||||
|
{
|
||||||
|
for (MessageListener messageListener : messageListeners)
|
||||||
|
messageListener.onOfferRemoved(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Send message
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public boolean sendMessage(String message)
|
||||||
|
{
|
||||||
|
boolean result = false;
|
||||||
|
if (otherPeerAddress != null)
|
||||||
|
{
|
||||||
|
if (peerConnection != null)
|
||||||
|
peerConnection.close();
|
||||||
|
|
||||||
|
peerConnection = myPeerInstance.createPeerConnection(otherPeerAddress, 20);
|
||||||
|
if (!peerConnection.isClosed())
|
||||||
|
{
|
||||||
|
FutureResponse sendFuture = myPeerInstance.sendDirect(peerConnection).setObject(message).start();
|
||||||
|
sendFuture.addListener(new BaseFutureAdapter<BaseFuture>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void operationComplete(BaseFuture baseFuture) throws Exception
|
||||||
|
{
|
||||||
|
if (sendFuture.isSuccess())
|
||||||
|
{
|
||||||
|
final Object object = sendFuture.getObject();
|
||||||
|
Platform.runLater(() -> onResponseFromSend(object));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Platform.runLater(() -> onSendFailed());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onResponseFromSend(Object response)
|
||||||
|
{
|
||||||
|
for (MessageListener messageListener : messageListeners)
|
||||||
|
messageListener.onResponseFromSend(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onSendFailed()
|
||||||
|
{
|
||||||
|
for (MessageListener messageListener : messageListeners)
|
||||||
|
messageListener.onSendFailed();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Find peer
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public void findPeer(String pubKeyAsHex)
|
||||||
|
{
|
||||||
|
final FutureDHT getPeerAddressFuture = myPeerInstance.get(getPubKeyHash(pubKeyAsHex)).start();
|
||||||
|
getPeerAddressFuture.addListener(new BaseFutureAdapter<BaseFuture>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void operationComplete(BaseFuture baseFuture) throws Exception
|
||||||
|
{
|
||||||
|
final PeerAddress peerAddress = (PeerAddress) getPeerAddressFuture.getData().getObject();
|
||||||
|
Platform.runLater(() -> onPeerFound(peerAddress));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onPeerFound(PeerAddress peerAddress)
|
||||||
|
{
|
||||||
|
if (!peerAddress.equals(myPeerInstance.getPeerAddress()))
|
||||||
|
{
|
||||||
|
otherPeerAddress = peerAddress;
|
||||||
|
for (MessageListener messageListener : messageListeners)
|
||||||
|
messageListener.onPeerFound();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Misc
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public boolean isOtherPeerDefined()
|
||||||
|
{
|
||||||
|
return otherPeerAddress != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPubKeyAsHex()
|
||||||
|
{
|
||||||
|
return Utils.bytesToHexString(keyPair.getPublic().getEncoded());
|
||||||
|
}
|
||||||
|
|
||||||
|
public PublicKey getPubKey()
|
||||||
|
{
|
||||||
|
return keyPair.getPublic();
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Event Listeners
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public void addMessageListener(MessageListener listener)
|
||||||
|
{
|
||||||
|
messageListeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeMessageListener(MessageListener listener)
|
||||||
|
{
|
||||||
|
messageListeners.remove(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Private Methods
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
private void createMyPeerInstance(String keyName, int port) throws IOException
|
||||||
|
{
|
||||||
|
keyPair = MsgKeyUtil.getKeyPair(keyName);
|
||||||
|
myPeerInstance = new PeerMaker(keyPair).setPorts(port).makeAndListen();
|
||||||
|
|
||||||
|
//TODO use list of multiple master bootstrap peers
|
||||||
|
/*PeerAddress bootstrapServerPeerAddress = new PeerAddress(BootstrapMasterPeer.ID, new InetSocketAddress(InetAddress.getByName(MASTER_PEER_IP), port));
|
||||||
|
FutureBootstrap futureBootstrap = myPeerInstance.bootstrap().setPeerAddress(bootstrapServerPeerAddress).start();
|
||||||
|
*/
|
||||||
|
FutureBootstrap futureBootstrap = myPeerInstance.bootstrap().setBroadcast().setPorts(MASTER_PEER_PORT).start();
|
||||||
|
if (futureBootstrap != null)
|
||||||
|
{
|
||||||
|
futureBootstrap.awaitUninterruptibly();
|
||||||
|
if (futureBootstrap.getBootstrapTo() != null)
|
||||||
|
{
|
||||||
|
PeerAddress peerAddress = futureBootstrap.getBootstrapTo().iterator().next();
|
||||||
|
myPeerInstance.discover().setPeerAddress(peerAddress).start().awaitUninterruptibly();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupStorage() throws IOException
|
||||||
|
{
|
||||||
|
//TODO WalletFacade.WALLET_PREFIX just temp...
|
||||||
|
String dirPath = io.bitsquare.util.Utils.getRootDir() + "tomP2P_" + WalletFacade.WALLET_PREFIX;
|
||||||
|
File dirFile = new File(dirPath);
|
||||||
|
boolean success = true;
|
||||||
|
if (!dirFile.exists())
|
||||||
|
success = dirFile.mkdir();
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
myPeerInstance.getPeerBean().setStorage(new StorageDisk(dirPath));
|
||||||
|
else
|
||||||
|
log.warn("Unable to create directory " + dirPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveMyAddressToDHT() throws IOException
|
||||||
|
{
|
||||||
|
myPeerInstance.put(getPubKeyHash(getPubKeyAsHex())).setData(new Data(myPeerInstance.getPeerAddress())).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Incoming message handler
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
private void setupReplyHandler()
|
||||||
|
{
|
||||||
|
myPeerInstance.setObjectDataReply(new ObjectDataReply()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Object reply(PeerAddress sender, Object request) throws Exception
|
||||||
|
{
|
||||||
|
String reply = null;
|
||||||
|
if (!sender.equals(myPeerInstance.getPeerAddress()))
|
||||||
|
{
|
||||||
|
otherPeerAddress = sender;
|
||||||
|
|
||||||
|
Platform.runLater(() -> onMessage(request));
|
||||||
|
if (request.equals(PING))
|
||||||
|
{
|
||||||
|
Platform.runLater(() -> onPing());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onMessage(Object message)
|
||||||
|
{
|
||||||
|
for (MessageListener messageListener : messageListeners)
|
||||||
|
messageListener.onMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onPing()
|
||||||
|
{
|
||||||
|
for (MessageListener messageListener : messageListeners)
|
||||||
|
messageListener.onPing();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Utils
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
private Number160 getPubKeyHash(String pubKeyAsHex)
|
||||||
|
{
|
||||||
|
return net.tomp2p.utils.Utils.makeSHAHash(pubKeyAsHex);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
26
src/main/java/io/bitsquare/msg/MessageListener.java
Normal file
26
src/main/java/io/bitsquare/msg/MessageListener.java
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
package io.bitsquare.msg;
|
||||||
|
|
||||||
|
import net.tomp2p.peers.Number160;
|
||||||
|
import net.tomp2p.storage.Data;
|
||||||
|
|
||||||
|
import java.util.EventListener;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface MessageListener extends EventListener
|
||||||
|
{
|
||||||
|
void onMessage(Object message);
|
||||||
|
|
||||||
|
void onPing();
|
||||||
|
|
||||||
|
void onOfferPublished(boolean success);
|
||||||
|
|
||||||
|
void onSendFailed();
|
||||||
|
|
||||||
|
void onResponseFromSend(Object response);
|
||||||
|
|
||||||
|
void onPeerFound();
|
||||||
|
|
||||||
|
void onOffersReceived(Map<Number160, Data> dataMap, boolean success);
|
||||||
|
|
||||||
|
void onOfferRemoved(boolean success);
|
||||||
|
}
|
131
src/main/java/io/bitsquare/msg/MsgKeyUtil.java
Executable file
131
src/main/java/io/bitsquare/msg/MsgKeyUtil.java
Executable file
|
@ -0,0 +1,131 @@
|
||||||
|
package io.bitsquare.msg;
|
||||||
|
|
||||||
|
import io.bitsquare.util.Utils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.spec.InvalidKeySpecException;
|
||||||
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
|
|
||||||
|
public class MsgKeyUtil
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(MsgKeyUtil.class);
|
||||||
|
private static final String baseDir = Utils.getRootDir();
|
||||||
|
|
||||||
|
public static KeyPair getKeyPair()
|
||||||
|
{
|
||||||
|
return getKeyPair("public.key", "private.key");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static KeyPair getKeyPair(String keyName)
|
||||||
|
{
|
||||||
|
return getKeyPair("public_" + keyName + ".key", "private_" + keyName + ".key");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static KeyPair getKeyPair(String pubKeyPath, String privKeyPath)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
KeyPair loadedKeyPair = loadKeyPair(pubKeyPath, privKeyPath, "DSA");
|
||||||
|
//System.out.println("Loaded Key Pair");
|
||||||
|
return loadedKeyPair;
|
||||||
|
} catch (Exception e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA");
|
||||||
|
|
||||||
|
keyGen.initialize(1024);
|
||||||
|
KeyPair generatedKeyPair = keyGen.genKeyPair();
|
||||||
|
|
||||||
|
// System.out.println("Generated Key Pair");
|
||||||
|
dumpKeyPair(generatedKeyPair);
|
||||||
|
saveKeyPair(pubKeyPath, privKeyPath, generatedKeyPair);
|
||||||
|
return generatedKeyPair;
|
||||||
|
} catch (Exception e2)
|
||||||
|
{
|
||||||
|
e2.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void dumpKeyPair(KeyPair keyPair)
|
||||||
|
{
|
||||||
|
PublicKey pub = keyPair.getPublic();
|
||||||
|
// System.out.println("Public Key: " + getHexString(pub.getEncoded()));
|
||||||
|
|
||||||
|
PrivateKey priv = keyPair.getPrivate();
|
||||||
|
// System.out.println("Private Key: " + getHexString(priv.getEncoded()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getHexString(byte[] b)
|
||||||
|
{
|
||||||
|
String result = "";
|
||||||
|
for (int i = 0; i < b.length; i++)
|
||||||
|
{
|
||||||
|
result += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void saveKeyPair(String pubKeyPath, String privKeyPath, KeyPair keyPair) throws IOException
|
||||||
|
{
|
||||||
|
PrivateKey privateKey = keyPair.getPrivate();
|
||||||
|
PublicKey publicKey = keyPair.getPublic();
|
||||||
|
|
||||||
|
// Store Public Key.
|
||||||
|
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(
|
||||||
|
publicKey.getEncoded());
|
||||||
|
FileOutputStream fos = new FileOutputStream(baseDir + pubKeyPath);
|
||||||
|
fos.write(x509EncodedKeySpec.getEncoded());
|
||||||
|
fos.close();
|
||||||
|
|
||||||
|
// Store Private Key.
|
||||||
|
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(
|
||||||
|
privateKey.getEncoded());
|
||||||
|
fos = new FileOutputStream(baseDir + privKeyPath);
|
||||||
|
fos.write(pkcs8EncodedKeySpec.getEncoded());
|
||||||
|
fos.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static KeyPair loadKeyPair(String pubKeyPath, String privKeyPath, String algorithm)
|
||||||
|
throws IOException, NoSuchAlgorithmException,
|
||||||
|
InvalidKeySpecException
|
||||||
|
{
|
||||||
|
// Read Public Key.
|
||||||
|
File filePublicKey = new File(baseDir + pubKeyPath);
|
||||||
|
FileInputStream fis = new FileInputStream(baseDir + pubKeyPath);
|
||||||
|
byte[] encodedPublicKey = new byte[(int) filePublicKey.length()];
|
||||||
|
fis.read(encodedPublicKey);
|
||||||
|
fis.close();
|
||||||
|
|
||||||
|
// Read Private Key.
|
||||||
|
File filePrivateKey = new File(baseDir + privKeyPath);
|
||||||
|
fis = new FileInputStream(baseDir + privKeyPath);
|
||||||
|
byte[] encodedPrivateKey = new byte[(int) filePrivateKey.length()];
|
||||||
|
fis.read(encodedPrivateKey);
|
||||||
|
fis.close();
|
||||||
|
|
||||||
|
// Generate KeyPair.
|
||||||
|
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
|
||||||
|
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(
|
||||||
|
encodedPublicKey);
|
||||||
|
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
|
||||||
|
|
||||||
|
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(
|
||||||
|
encodedPrivateKey);
|
||||||
|
PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
|
||||||
|
|
||||||
|
return new KeyPair(publicKey, privateKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package io.bitsquare.storage;
|
package io.bitsquare.storage;
|
||||||
|
|
||||||
|
import io.bitsquare.util.Utils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -26,7 +27,7 @@ public class Storage
|
||||||
|
|
||||||
public Storage()
|
public Storage()
|
||||||
{
|
{
|
||||||
storageFile = Storage.class.getProtectionDomain().getCodeSource().getLocation().getFile() + "/" + preferencesFileName;
|
storageFile = Utils.getRootDir() + preferencesFileName;
|
||||||
|
|
||||||
dict = readDataVO();
|
dict = readDataVO();
|
||||||
if (dict == null)
|
if (dict == null)
|
||||||
|
|
|
@ -11,15 +11,18 @@ import java.util.UUID;
|
||||||
|
|
||||||
public class Offer
|
public class Offer
|
||||||
{
|
{
|
||||||
|
// key attributes for lookup
|
||||||
|
private Direction direction;
|
||||||
|
private Currency currency;
|
||||||
|
|
||||||
private UUID uid;
|
private UUID uid;
|
||||||
|
|
||||||
private double price;
|
private double price;
|
||||||
private BigInteger amount;
|
private BigInteger amount;
|
||||||
private BigInteger minAmount;
|
private BigInteger minAmount;
|
||||||
private String accountID;
|
private String accountID;
|
||||||
private String messageID;
|
private String messageID;
|
||||||
private Direction direction;
|
|
||||||
private BankAccountType.BankAccountTypeEnum bankAccountTypeEnum;
|
private BankAccountType.BankAccountTypeEnum bankAccountTypeEnum;
|
||||||
private Currency currency;
|
|
||||||
private Locale bankAccountCountryLocale;
|
private Locale bankAccountCountryLocale;
|
||||||
|
|
||||||
private double collateral;
|
private double collateral;
|
||||||
|
|
|
@ -9,7 +9,6 @@ import io.bitsquare.btc.Fees;
|
||||||
import io.bitsquare.btc.KeyPair;
|
import io.bitsquare.btc.KeyPair;
|
||||||
import io.bitsquare.btc.WalletFacade;
|
import io.bitsquare.btc.WalletFacade;
|
||||||
import io.bitsquare.crypto.CryptoFacade;
|
import io.bitsquare.crypto.CryptoFacade;
|
||||||
import io.bitsquare.msg.Message;
|
|
||||||
import io.bitsquare.msg.MessageFacade;
|
import io.bitsquare.msg.MessageFacade;
|
||||||
import io.bitsquare.settings.Settings;
|
import io.bitsquare.settings.Settings;
|
||||||
import io.bitsquare.user.User;
|
import io.bitsquare.user.User;
|
||||||
|
@ -70,7 +69,7 @@ public class Trading
|
||||||
offers.put(offer.getUid().toString(), offer);
|
offers.put(offer.getUid().toString(), offer);
|
||||||
walletFacade.payFee(Fees.OFFER_CREATION_FEE, callback);
|
walletFacade.payFee(Fees.OFFER_CREATION_FEE, callback);
|
||||||
|
|
||||||
messageFacade.broadcast(new Message(Message.BROADCAST_NEW_OFFER, offer));
|
// messageFacade.broadcast(new Message(Message.BROADCAST_NEW_OFFER, offer));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Trade createTrade(Offer offer)
|
public Trade createTrade(Offer offer)
|
||||||
|
|
|
@ -21,6 +21,12 @@ public class Utils
|
||||||
{
|
{
|
||||||
private static final Logger log = LoggerFactory.getLogger(Utils.class);
|
private static final Logger log = LoggerFactory.getLogger(Utils.class);
|
||||||
|
|
||||||
|
public static String getRootDir()
|
||||||
|
{
|
||||||
|
return Utils.class.getProtectionDomain().getCodeSource().getLocation().getFile() + "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static String objectToJson(Object object)
|
public static String objectToJson(Object object)
|
||||||
{
|
{
|
||||||
Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).create();
|
Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).create();
|
||||||
|
|
|
@ -13,14 +13,17 @@
|
||||||
<appender-ref ref="CONSOLE_APPENDER"/>
|
<appender-ref ref="CONSOLE_APPENDER"/>
|
||||||
</root>
|
</root>
|
||||||
|
|
||||||
<logger name="io.bitsquare" level="DEBUG"/>
|
<logger name="io.bitsquare" level="INFO"/>
|
||||||
|
|
||||||
|
<logger name="com.google.bitcoin" level="ERROR"/>
|
||||||
|
<logger name="net.tomp2p" level="INFO"/>
|
||||||
|
|
||||||
<logger name="com.google.bitcoin" level="INFO"/>
|
|
||||||
|
|
||||||
<logger name="com.google.bitcoin.core.Peer" level="ERROR" additivity="false"/>
|
<logger name="com.google.bitcoin.core.Peer" level="ERROR" additivity="false"/>
|
||||||
<logger name="com.google.bitcoin.core.PeerGroup" level="ERROR" additivity="false"/>
|
<logger name="com.google.bitcoin.core.PeerGroup" level="ERROR" additivity="false"/>
|
||||||
<logger name="com.google.bitcoin.net.NioClientManager" level="ERROR" additivity="false"/>
|
<logger name="com.google.bitcoin.net.NioClientManager" level="ERROR" additivity="false"/>
|
||||||
<logger name="com.google.bitcoin.net.ConnectionHandler" level="ERROR" additivity="false"/>
|
<logger name="com.google.bitcoin.net.ConnectionHandler" level="ERROR" additivity="false"/>
|
||||||
|
<logger name="com.google.bitcoin.net.discovery.DnsDiscovery" level="OFF" additivity="false"/>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
-->
|
-->
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue