mirror of
https://github.com/boldsuck/haveno.git
synced 2024-12-22 12:09:22 +00:00
Merge branch 'haveno-dex:master' into haveno-reto
This commit is contained in:
commit
82c0904d50
16 changed files with 113 additions and 91 deletions
|
@ -73,18 +73,9 @@ To incentivize development and reward contributors, we adopt a simple bounty sys
|
|||
|
||||
To bring Haveno to life, we need resources. If you have the possibility, please consider [becoming a sponsor](https://haveno.exchange/sponsors/) or donating to the project:
|
||||
|
||||
### Monero
|
||||
|
||||
<p>
|
||||
<img src="https://raw.githubusercontent.com/haveno-dex/haveno/master/media/donate_monero.png" alt="Donate Monero" width="115" height="115"><br>
|
||||
<code>42sjokkT9FmiWPqVzrWPFE5NCJXwt96bkBozHf4vgLR9hXyJDqKHEHKVscAARuD7in5wV1meEcSTJTanCTDzidTe2cFXS1F</code>
|
||||
</p>
|
||||
|
||||
If you are using a wallet that supports OpenAlias (like the 'official' CLI and GUI wallets), you can simply put `fund@haveno.exchange` as the "receiver" address.
|
||||
|
||||
### Bitcoin
|
||||
|
||||
<p>
|
||||
<img src="https://raw.githubusercontent.com/haveno-dex/haveno/master/media/donate_bitcoin.png" alt="Donate Bitcoin" width="115" height="115"><br>
|
||||
<code>1AKq3CE1yBAnxGmHXbNFfNYStcByNDc5gQ</code>
|
||||
</p>
|
||||
|
|
|
@ -610,7 +610,7 @@ configure(project(':desktop')) {
|
|||
apply plugin: 'com.github.johnrengelman.shadow'
|
||||
apply from: 'package/package.gradle'
|
||||
|
||||
version = '1.0.16-SNAPSHOT'
|
||||
version = '1.0.17-SNAPSHOT'
|
||||
|
||||
jar.manifest.attributes(
|
||||
"Implementation-Title": project.name,
|
||||
|
|
|
@ -28,7 +28,7 @@ import static com.google.common.base.Preconditions.checkArgument;
|
|||
public class Version {
|
||||
// The application versions
|
||||
// We use semantic versioning with major, minor and patch
|
||||
public static final String VERSION = "1.0.16";
|
||||
public static final String VERSION = "1.0.17";
|
||||
|
||||
/**
|
||||
* Holds a list of the tagged resource files for optimizing the getData requests.
|
||||
|
|
|
@ -115,7 +115,6 @@ import lombok.Getter;
|
|||
import monero.common.MoneroRpcConnection;
|
||||
import monero.daemon.model.MoneroKeyImageSpentStatus;
|
||||
import monero.daemon.model.MoneroTx;
|
||||
import monero.wallet.model.MoneroIncomingTransfer;
|
||||
import monero.wallet.model.MoneroOutputQuery;
|
||||
import monero.wallet.model.MoneroOutputWallet;
|
||||
import monero.wallet.model.MoneroTransferQuery;
|
||||
|
@ -1159,23 +1158,17 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||
|
||||
private void scheduleWithEarliestTxs(List<OpenOffer> openOffers, OpenOffer openOffer) {
|
||||
|
||||
// check for sufficient balance - scheduled offers amount
|
||||
BigInteger offerReserveAmount = openOffer.getOffer().getAmountNeeded();
|
||||
if (xmrWalletService.getBalance().subtract(getScheduledAmount(openOffers)).compareTo(offerReserveAmount) < 0) {
|
||||
throw new RuntimeException("Not enough money in Haveno wallet");
|
||||
}
|
||||
|
||||
// get earliest available or pending txs with sufficient spendable amount
|
||||
BigInteger offerReserveAmount = openOffer.getOffer().getAmountNeeded();
|
||||
BigInteger scheduledAmount = BigInteger.ZERO;
|
||||
Set<MoneroTxWallet> scheduledTxs = new HashSet<MoneroTxWallet>();
|
||||
for (MoneroTxWallet tx : xmrWalletService.getTxs()) {
|
||||
|
||||
// get spendable amount
|
||||
BigInteger spendableAmount = getSpendableAmount(tx);
|
||||
// get unscheduled spendable amount
|
||||
BigInteger spendableAmount = getUnscheduledSpendableAmount(tx, openOffers);
|
||||
|
||||
// skip if no spendable amount or already scheduled
|
||||
// skip if no spendable amount
|
||||
if (spendableAmount.equals(BigInteger.ZERO)) continue;
|
||||
if (isTxScheduledByOtherOffer(openOffers, openOffer, tx.getHash())) continue;
|
||||
|
||||
// schedule tx
|
||||
scheduledAmount = scheduledAmount.add(spendableAmount);
|
||||
|
@ -1184,7 +1177,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||
// break if sufficient funds
|
||||
if (scheduledAmount.compareTo(offerReserveAmount) >= 0) break;
|
||||
}
|
||||
if (scheduledAmount.compareTo(offerReserveAmount) < 0) throw new RuntimeException("Not enough funds to schedule offer");
|
||||
if (scheduledAmount.compareTo(offerReserveAmount) < 0) throw new RuntimeException("Not enough funds to create offer");
|
||||
|
||||
// schedule txs
|
||||
openOffer.setScheduledTxHashes(scheduledTxs.stream().map(tx -> tx.getHash()).collect(Collectors.toList()));
|
||||
|
@ -1192,6 +1185,30 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||
openOffer.setState(OpenOffer.State.PENDING);
|
||||
}
|
||||
|
||||
private BigInteger getUnscheduledSpendableAmount(MoneroTxWallet tx, List<OpenOffer> openOffers) {
|
||||
if (isScheduledWithUnknownAmount(tx, openOffers)) return BigInteger.ZERO;
|
||||
return getSpendableAmount(tx).subtract(getSplitAmount(tx, openOffers)).max(BigInteger.ZERO);
|
||||
}
|
||||
|
||||
private boolean isScheduledWithUnknownAmount(MoneroTxWallet tx, List<OpenOffer> openOffers) {
|
||||
for (OpenOffer openOffer : openOffers) {
|
||||
if (openOffer.getScheduledTxHashes() == null) continue;
|
||||
if (openOffer.getScheduledTxHashes().contains(tx.getHash()) && !tx.getHash().equals(openOffer.getSplitOutputTxHash())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private BigInteger getSplitAmount(MoneroTxWallet tx, List<OpenOffer> openOffers) {
|
||||
for (OpenOffer openOffer : openOffers) {
|
||||
if (openOffer.getSplitOutputTxHash() == null) continue;
|
||||
if (!openOffer.getSplitOutputTxHash().equals(tx.getHash())) continue;
|
||||
return openOffer.getOffer().getAmountNeeded();
|
||||
}
|
||||
return BigInteger.ZERO;
|
||||
}
|
||||
|
||||
private BigInteger getSpendableAmount(MoneroTxWallet tx) {
|
||||
|
||||
// compute spendable amount from outputs if confirmed
|
||||
|
@ -1220,23 +1237,6 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||
return getSpendableAmount(tx).compareTo(BigInteger.ZERO) > 0;
|
||||
}
|
||||
|
||||
private BigInteger getScheduledAmount(List<OpenOffer> openOffers) {
|
||||
BigInteger scheduledAmount = BigInteger.ZERO;
|
||||
for (OpenOffer openOffer : openOffers) {
|
||||
if (openOffer.getState() != OpenOffer.State.PENDING) continue;
|
||||
if (openOffer.getScheduledTxHashes() == null) continue;
|
||||
List<MoneroTxWallet> fundingTxs = xmrWalletService.getTxs(openOffer.getScheduledTxHashes());
|
||||
for (MoneroTxWallet fundingTx : fundingTxs) {
|
||||
if (fundingTx.getIncomingTransfers() != null) {
|
||||
for (MoneroIncomingTransfer transfer : fundingTx.getIncomingTransfers()) {
|
||||
if (transfer.getAccountIndex() == 0) scheduledAmount = scheduledAmount.add(transfer.getAmount());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return scheduledAmount;
|
||||
}
|
||||
|
||||
private boolean isTxScheduledByOtherOffer(List<OpenOffer> openOffers, OpenOffer openOffer, String txHash) {
|
||||
for (OpenOffer otherOffer : openOffers) {
|
||||
if (otherOffer == openOffer) continue;
|
||||
|
|
|
@ -60,6 +60,6 @@
|
|||
</content_rating>
|
||||
|
||||
<releases>
|
||||
<release version="1.0.16" date="2024-12-19"/>
|
||||
<release version="1.0.17" date="2024-12-21"/>
|
||||
</releases>
|
||||
</component>
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
<!-- See: https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -->
|
||||
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0.16</string>
|
||||
<string>1.0.17</string>
|
||||
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0.16</string>
|
||||
<string>1.0.17</string>
|
||||
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>Haveno</string>
|
||||
|
|
|
@ -38,8 +38,8 @@
|
|||
<TableColumn fx:id="transactionColumn" minWidth="180"/>
|
||||
<TableColumn fx:id="amountColumn" minWidth="110" maxWidth="110"/>
|
||||
<TableColumn fx:id="txFeeColumn" minWidth="110" maxWidth="110"/>
|
||||
<TableColumn fx:id="confidenceColumn" minWidth="60" maxWidth="130"/>
|
||||
<TableColumn fx:id="memoColumn" minWidth="40"/>
|
||||
<TableColumn fx:id="confidenceColumn" minWidth="120" maxWidth="130"/>
|
||||
<TableColumn fx:id="revertTxColumn" sortable="false" minWidth="110" maxWidth="110" visible="false"/>
|
||||
</columns>
|
||||
</TableView>
|
||||
|
|
|
@ -70,7 +70,7 @@ public class TransactionsView extends ActivatableView<VBox, Void> {
|
|||
@FXML
|
||||
TableView<TransactionsListItem> tableView;
|
||||
@FXML
|
||||
TableColumn<TransactionsListItem, TransactionsListItem> dateColumn, detailsColumn, addressColumn, transactionColumn, amountColumn, txFeeColumn, memoColumn, confidenceColumn, revertTxColumn;
|
||||
TableColumn<TransactionsListItem, TransactionsListItem> dateColumn, detailsColumn, addressColumn, transactionColumn, amountColumn, txFeeColumn, confidenceColumn, memoColumn, revertTxColumn;
|
||||
@FXML
|
||||
Label numItems;
|
||||
@FXML
|
||||
|
@ -133,8 +133,8 @@ public class TransactionsView extends ActivatableView<VBox, Void> {
|
|||
transactionColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.txId", Res.getBaseCurrencyCode())));
|
||||
amountColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.amountWithCur", Res.getBaseCurrencyCode())));
|
||||
txFeeColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.txFee", Res.getBaseCurrencyCode())));
|
||||
memoColumn.setGraphic(new AutoTooltipLabel(Res.get("funds.tx.memo")));
|
||||
confidenceColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.confirmations", Res.getBaseCurrencyCode())));
|
||||
memoColumn.setGraphic(new AutoTooltipLabel(Res.get("funds.tx.memo")));
|
||||
revertTxColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.revert", Res.getBaseCurrencyCode())));
|
||||
|
||||
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY_FLEX_LAST_COLUMN);
|
||||
|
@ -146,8 +146,8 @@ public class TransactionsView extends ActivatableView<VBox, Void> {
|
|||
setTransactionColumnCellFactory();
|
||||
setAmountColumnCellFactory();
|
||||
setTxFeeColumnCellFactory();
|
||||
setMemoColumnCellFactory();
|
||||
setConfidenceColumnCellFactory();
|
||||
setMemoColumnCellFactory();
|
||||
setRevertTxColumnCellFactory();
|
||||
|
||||
dateColumn.setComparator(Comparator.comparing(TransactionsListItem::getDate));
|
||||
|
@ -221,8 +221,8 @@ public class TransactionsView extends ActivatableView<VBox, Void> {
|
|||
columns[3] = item.getTxId();
|
||||
columns[4] = item.getAmountStr();
|
||||
columns[5] = item.getTxFeeStr();
|
||||
columns[6] = item.getMemo() == null ? "" : item.getMemo();
|
||||
columns[7] = String.valueOf(item.getNumConfirmations());
|
||||
columns[6] = String.valueOf(item.getNumConfirmations());
|
||||
columns[7] = item.getMemo() == null ? "" : item.getMemo();
|
||||
return columns;
|
||||
};
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ import haveno.core.util.coin.CoinUtil;
|
|||
import haveno.core.util.validation.AmountValidator4Decimals;
|
||||
import haveno.core.util.validation.AmountValidator8Decimals;
|
||||
import haveno.core.util.validation.InputValidator;
|
||||
import haveno.core.util.validation.InputValidator.ValidationResult;
|
||||
import haveno.core.util.validation.MonetaryValidator;
|
||||
import haveno.core.xmr.wallet.Restrictions;
|
||||
import haveno.desktop.Navigation;
|
||||
|
@ -490,6 +491,8 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
|||
xmrValidator.setMaxTradeLimit(BigInteger.valueOf(dataModel.getMaxTradeLimit()));
|
||||
if (amount.get() != null) amountValidationResult.set(isXmrInputValid(amount.get()));
|
||||
updateSecurityDeposit();
|
||||
setSecurityDepositToModel();
|
||||
onFocusOutSecurityDepositTextField(true, false); // refresh security deposit field
|
||||
applyMakerFee();
|
||||
dataModel.calculateTotalToPay();
|
||||
updateButtonDisableState();
|
||||
|
@ -769,7 +772,8 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
|||
}
|
||||
}
|
||||
}
|
||||
// We want to trigger a recalculation of the volume
|
||||
|
||||
// trigger recalculation of the volume
|
||||
UserThread.execute(() -> {
|
||||
onFocusOutVolumeTextField(true, false);
|
||||
onFocusOutMinAmountTextField(true, false);
|
||||
|
@ -815,6 +819,11 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
|||
}
|
||||
|
||||
maybeShowMakeOfferToUnsignedAccountWarning();
|
||||
|
||||
// trigger recalculation of the security deposit
|
||||
UserThread.execute(() -> {
|
||||
onFocusOutSecurityDepositTextField(true, false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -944,11 +953,16 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
|||
if (marketPriceMargin.get() == null && amount.get() != null && volume.get() != null) {
|
||||
updateMarketPriceToManual();
|
||||
}
|
||||
|
||||
// trigger recalculation of security deposit
|
||||
UserThread.execute(() -> {
|
||||
onFocusOutSecurityDepositTextField(true, false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void onFocusOutSecurityDepositTextField(boolean oldValue, boolean newValue) {
|
||||
if (oldValue && !newValue) {
|
||||
if (oldValue && !newValue && !isMinSecurityDeposit.get()) {
|
||||
InputValidator.ValidationResult result = securityDepositValidator.validate(securityDeposit.get());
|
||||
securityDepositValidationResult.set(result);
|
||||
if (result.isValid) {
|
||||
|
@ -1040,6 +1054,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
|||
|
||||
public String getSecurityDepositLabel() {
|
||||
return dataModel.buyerAsTakerWithoutDeposit.get() && dataModel.isSellOffer() ? Res.get("createOffer.myDeposit") :
|
||||
dataModel.isMinSecurityDeposit() ? Res.get("createOffer.minSecurityDepositUsed") :
|
||||
Preferences.USE_SYMMETRIC_SECURITY_DEPOSIT ? Res.get("createOffer.setDepositForBothTraders") :
|
||||
dataModel.isBuyOffer() ? Res.get("createOffer.setDepositAsBuyer") : Res.get("createOffer.setDeposit");
|
||||
}
|
||||
|
@ -1211,7 +1226,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
|||
}
|
||||
|
||||
private void setSecurityDepositToModel() {
|
||||
if (!(dataModel.buyerAsTakerWithoutDeposit.get() && dataModel.isSellOffer()) && securityDeposit.get() != null && !securityDeposit.get().isEmpty()) {
|
||||
if (securityDeposit.get() != null && !securityDeposit.get().isEmpty() && !isMinSecurityDeposit.get()) {
|
||||
dataModel.setSecurityDepositPct(ParsingUtils.parsePercentStringToDouble(securityDeposit.get()));
|
||||
} else {
|
||||
dataModel.setSecurityDepositPct(Restrictions.getDefaultSecurityDepositAsPercent());
|
||||
|
@ -1282,11 +1297,11 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
|||
|
||||
private void updateSecurityDeposit() {
|
||||
isMinSecurityDeposit.set(dataModel.isMinSecurityDeposit());
|
||||
securityDepositLabel.set(getSecurityDepositLabel());
|
||||
if (dataModel.isMinSecurityDeposit()) {
|
||||
securityDepositLabel.set(Res.get("createOffer.minSecurityDepositUsed"));
|
||||
securityDeposit.set(HavenoUtils.formatXmr(Restrictions.getMinSecurityDeposit()));
|
||||
securityDepositValidationResult.set(new ValidationResult(true));
|
||||
} else {
|
||||
securityDepositLabel.set(getSecurityDepositLabel());
|
||||
boolean hasBuyerAsTakerWithoutDeposit = dataModel.buyerAsTakerWithoutDeposit.get() && dataModel.isSellOffer();
|
||||
securityDeposit.set(FormattingUtils.formatToPercent(hasBuyerAsTakerWithoutDeposit ?
|
||||
Restrictions.getDefaultSecurityDepositAsPercent() : // use default percent if no deposit from buyer
|
||||
|
|
|
@ -185,7 +185,7 @@ abstract public class OfferBookView<R extends GridPane, M extends OfferBookViewM
|
|||
paymentMethodComboBox.setCellFactory(GUIUtil.getPaymentMethodCellFactory());
|
||||
paymentMethodComboBox.setPrefWidth(250);
|
||||
|
||||
matchingOffersToggleButton = AwesomeDude.createIconToggleButton(AwesomeIcon.USER, null, "1.3em", null);
|
||||
matchingOffersToggleButton = AwesomeDude.createIconToggleButton(AwesomeIcon.USER, null, "1.5em", null);
|
||||
matchingOffersToggleButton.getStyleClass().add("toggle-button-no-slider");
|
||||
matchingOffersToggleButton.setPrefHeight(27);
|
||||
Tooltip matchingOffersTooltip = new Tooltip(Res.get("offerbook.matchingOffers"));
|
||||
|
@ -1069,39 +1069,39 @@ abstract public class OfferBookView<R extends GridPane, M extends OfferBookViewM
|
|||
return new TableCell<>() {
|
||||
OfferFilterService.Result canTakeOfferResult = null;
|
||||
|
||||
final ImageView iconView = new ImageView();
|
||||
final AutoTooltipButton button = new AutoTooltipButton();
|
||||
|
||||
{
|
||||
button.setGraphic(iconView);
|
||||
button.setGraphicTextGap(10);
|
||||
button.setPrefWidth(10000);
|
||||
}
|
||||
|
||||
final ImageView iconView2 = new ImageView();
|
||||
final AutoTooltipButton button2 = new AutoTooltipButton();
|
||||
|
||||
{
|
||||
button2.setGraphic(iconView2);
|
||||
button2.setGraphicTextGap(10);
|
||||
button2.setPrefWidth(10000);
|
||||
}
|
||||
|
||||
final HBox hbox = new HBox();
|
||||
|
||||
{
|
||||
hbox.setSpacing(8);
|
||||
hbox.setAlignment(Pos.CENTER);
|
||||
hbox.getChildren().add(button);
|
||||
hbox.getChildren().add(button2);
|
||||
HBox.setHgrow(button, Priority.ALWAYS);
|
||||
HBox.setHgrow(button2, Priority.ALWAYS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateItem(final OfferBookListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
|
||||
final ImageView iconView = new ImageView();
|
||||
final AutoTooltipButton button = new AutoTooltipButton();
|
||||
|
||||
{
|
||||
button.setGraphic(iconView);
|
||||
button.setGraphicTextGap(10);
|
||||
button.setPrefWidth(10000);
|
||||
}
|
||||
|
||||
final ImageView iconView2 = new ImageView();
|
||||
final AutoTooltipButton button2 = new AutoTooltipButton();
|
||||
|
||||
{
|
||||
button2.setGraphic(iconView2);
|
||||
button2.setGraphicTextGap(10);
|
||||
button2.setPrefWidth(10000);
|
||||
}
|
||||
|
||||
final HBox hbox = new HBox();
|
||||
|
||||
{
|
||||
hbox.setSpacing(8);
|
||||
hbox.setAlignment(Pos.CENTER);
|
||||
hbox.getChildren().add(button);
|
||||
hbox.getChildren().add(button2);
|
||||
HBox.setHgrow(button, Priority.ALWAYS);
|
||||
HBox.setHgrow(button2, Priority.ALWAYS);
|
||||
}
|
||||
|
||||
TableRow<OfferBookListItem> tableRow = getTableRow();
|
||||
if (item != null && !empty) {
|
||||
Offer offer = item.getOffer();
|
||||
|
|
|
@ -260,7 +260,10 @@ abstract class OfferBookViewModel extends ActivatableViewModel {
|
|||
showAllTradeCurrenciesProperty.set(showAllEntry);
|
||||
if (isEditEntry(code))
|
||||
navigation.navigateTo(MainView.class, SettingsView.class, PreferencesView.class);
|
||||
else if (!showAllEntry) {
|
||||
else if (showAllEntry) {
|
||||
this.selectedTradeCurrency = getDefaultTradeCurrency();
|
||||
tradeCurrencyCode.set(selectedTradeCurrency.getCode());
|
||||
} else {
|
||||
this.selectedTradeCurrency = tradeCurrency;
|
||||
tradeCurrencyCode.set(code);
|
||||
}
|
||||
|
@ -579,7 +582,10 @@ abstract class OfferBookViewModel extends ActivatableViewModel {
|
|||
getCurrencyAndMethodPredicate(direction, selectedTradeCurrency).and(getOffersMatchingMyAccountsPredicate()) :
|
||||
getCurrencyAndMethodPredicate(direction, selectedTradeCurrency);
|
||||
|
||||
predicate = predicate.and(offerBookListItem -> offerBookListItem.getOffer().isPrivateOffer() == showPrivateOffers);
|
||||
// filter private offers
|
||||
if (direction == OfferDirection.BUY) {
|
||||
predicate = predicate.and(offerBookListItem -> offerBookListItem.getOffer().isPrivateOffer() == showPrivateOffers);
|
||||
}
|
||||
|
||||
if (!filterText.isEmpty()) {
|
||||
|
||||
|
|
|
@ -561,8 +561,10 @@
|
|||
.toggle-button-no-slider {
|
||||
-fx-focus-color: transparent;
|
||||
-fx-faint-focus-color: transparent;
|
||||
-fx-background-radius: 3;
|
||||
-fx-background-insets: 0, 1;
|
||||
}
|
||||
|
||||
.toggle-button-no-slider:selected {
|
||||
-fx-background-color: -bs-color-gray-ddd;
|
||||
-fx-background-color: -bs-color-gray-bbb;
|
||||
}
|
||||
|
|
|
@ -118,6 +118,10 @@ The price node is separated from Haveno and is run as a standalone service. To d
|
|||
|
||||
After the price node is built and deployed, add the price node to `DEFAULT_NODES` in [ProvidersRepository.java](https://github.com/haveno-dex/haveno/blob/3cdd88b56915c7f8afd4f1a39e6c1197c2665d63/core/src/main/java/haveno/core/provider/ProvidersRepository.java#L50).
|
||||
|
||||
### Update the download URL
|
||||
|
||||
Change every instance of `https://haveno.exchange/downloads` to your download URL. For example, `https://havenoexample.com/downloads`.
|
||||
|
||||
## Review all local changes
|
||||
|
||||
For comparison, placeholders to run on mainnet are marked [here on this branch](https://github.com/haveno-dex/haveno/tree/mainnet_placeholders).
|
||||
|
|
|
@ -243,6 +243,10 @@ Set `ARBITRATOR_ASSIGNS_TRADE_FEE_ADDRESS` to `true` for the arbitrator to assig
|
|||
|
||||
Otherwise set `ARBITRATOR_ASSIGNS_TRADE_FEE_ADDRESS` to `false` and set the XMR address in `getGlobalTradeFeeAddress()` to collect all trade fees to a single address (e.g. a multisig wallet shared among network administrators).
|
||||
|
||||
## Update the download URL
|
||||
|
||||
Change every instance of `https://haveno.exchange/downloads` to your download URL. For example, `https://havenoexample.com/downloads`.
|
||||
|
||||
## Start users for testing
|
||||
|
||||
Start user1 on Monero's mainnet using `make user1-desktop-mainnet` or Monero's stagenet using `make user1-desktop-stagenet`.
|
||||
|
@ -266,7 +270,7 @@ Then follow these instructions: https://github.com/haveno-dex/haveno/blob/master
|
|||
|
||||
<b>Set the mandatory minimum version for trading (optional)</b>
|
||||
|
||||
If applicable, update the mandatory minimum version for trading, by entering `ctrl + f` to open the Filter window, enter a private key with developer privileges, and enter the minimum version (e.g. 1.0.16) in the field labeled "Min. version required for trading".
|
||||
If applicable, update the mandatory minimum version for trading, by entering `ctrl + f` to open the Filter window, enter a private key with developer privileges, and enter the minimum version (e.g. 1.0.17) in the field labeled "Min. version required for trading".
|
||||
|
||||
<b>Send update alert</b>
|
||||
|
||||
|
|
|
@ -31,8 +31,8 @@ Follow [instructions](https://github.com/haveno-dex/haveno-ts#run-tests) to run
|
|||
For example, the gRPC function to get offers is implemented by [`GrpcServer`](https://github.com/haveno-dex/haveno/blob/master/daemon/src/main/java/haveno/daemon/grpc/GrpcServer.java) > [`GrpcOffersService.getOffers(...)`](https://github.com/haveno-dex/haveno/blob/b761dbfd378faf49d95090c126318b419af7926b/daemon/src/main/java/haveno/daemon/grpc/GrpcOffersService.java#L104) > [`CoreApi.getOffers(...)`](https://github.com/haveno-dex/haveno/blob/b761dbfd378faf49d95090c126318b419af7926b/core/src/main/java/haveno/core/api/CoreApi.java#L128) > [`CoreOffersService.getOffers(...)`](https://github.com/haveno-dex/haveno/blob/b761dbfd378faf49d95090c126318b419af7926b/core/src/main/java/haveno/core/api/CoreOffersService.java#L126) > [`OfferBookService.getOffers()`](https://github.com/haveno-dex/haveno/blob/b761dbfd378faf49d95090c126318b419af7926b/core/src/main/java/haveno/core/offer/OfferBookService.java#L193).
|
||||
5. Build Haveno: `make`
|
||||
6. Update the gRPC client in haveno-ts: `npm install`
|
||||
7. Add the corresponding typescript method(s) to [haveno.ts](https://github.com/haveno-dex/haveno-ts/blob/master/src/haveno.ts) with clear and concise documentation.
|
||||
8. Add clean and comprehensive tests to [haveno.test.ts](https://github.com/haveno-dex/haveno-ts/blob/master/src/haveno.test.ts), following existing patterns.
|
||||
7. Add the corresponding typescript method(s) to [HavenoClient.ts](https://github.com/haveno-dex/haveno-ts/blob/master/src/HavenoClient.ts) with clear and concise documentation.
|
||||
8. Add clean and comprehensive tests to [HavenoClient.test.ts](https://github.com/haveno-dex/haveno-ts/blob/master/src/HavenoClient.test.ts), following existing patterns.
|
||||
9. Run the tests with `npm run test -- -t 'my test'` to run tests by name and `npm test` to run all tests together. Ensure all tests pass and there are no exception stacktraces in the terminals of Alice, Bob, or the arbitrator.
|
||||
10. Open pull requests to the haveno and haveno-ts projects for the backend and frontend implementations.
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||
@Slf4j
|
||||
public class SeedNodeMain extends ExecutableForAppWithP2p {
|
||||
private static final long CHECK_CONNECTION_LOSS_SEC = 30;
|
||||
private static final String VERSION = "1.0.16";
|
||||
private static final String VERSION = "1.0.17";
|
||||
private SeedNode seedNode;
|
||||
private Timer checkConnectionLossTime;
|
||||
|
||||
|
|
Loading…
Reference in a new issue