mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2025-01-27 10:51:09 +00:00
Merge branch 'master' into patch-satochip-multisig
This commit is contained in:
commit
f4b3b3d55a
10 changed files with 54 additions and 23 deletions
|
@ -48,7 +48,7 @@ tasks.withType(AbstractArchiveTask) {
|
||||||
}
|
}
|
||||||
|
|
||||||
javafx {
|
javafx {
|
||||||
version = headless ? "18" : "22"
|
version = headless ? "18" : "23.0.1"
|
||||||
modules = [ 'javafx.controls', 'javafx.fxml', 'javafx.swing', 'javafx.graphics' ]
|
modules = [ 'javafx.controls', 'javafx.fxml', 'javafx.swing', 'javafx.graphics' ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -274,7 +274,7 @@ public class AppController implements Initializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
void initializeView() {
|
void initializeView() {
|
||||||
setPlatformApplicationMenu();
|
Platform.runLater(this::setPlatformApplicationMenu);
|
||||||
|
|
||||||
rootStack.getScene().getWindow().setOnHiding(windowEvent -> {
|
rootStack.getScene().getWindow().setOnHiding(windowEvent -> {
|
||||||
if(searchWalletDialog != null && searchWalletDialog.isShowing()) {
|
if(searchWalletDialog != null && searchWalletDialog.isShowing()) {
|
||||||
|
@ -450,7 +450,7 @@ public class AppController implements Initializable {
|
||||||
OsType osType = OsType.getCurrent();
|
OsType osType = OsType.getCurrent();
|
||||||
if(osType == OsType.MACOS) {
|
if(osType == OsType.MACOS) {
|
||||||
MenuToolkit tk = MenuToolkit.toolkit();
|
MenuToolkit tk = MenuToolkit.toolkit();
|
||||||
MenuItem preferences = new MenuItem("Preferences...");
|
MenuItem preferences = new MenuItem("Settings...");
|
||||||
preferences.setOnAction(this::openPreferences);
|
preferences.setOnAction(this::openPreferences);
|
||||||
preferences.setAccelerator(new KeyCodeCombination(KeyCode.COMMA, KeyCombination.META_DOWN));
|
preferences.setAccelerator(new KeyCodeCombination(KeyCode.COMMA, KeyCombination.META_DOWN));
|
||||||
Menu defaultApplicationMenu = new Menu("Apple", null, tk.createAboutMenuItem(SparrowWallet.APP_NAME, getAboutStage()), new SeparatorMenuItem(),
|
Menu defaultApplicationMenu = new Menu("Apple", null, tk.createAboutMenuItem(SparrowWallet.APP_NAME, getAboutStage()), new SeparatorMenuItem(),
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package com.sparrowwallet.sparrow.net;
|
||||||
|
|
||||||
|
public class ConfigurationException extends RuntimeException {
|
||||||
|
public ConfigurationException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfigurationException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,7 @@ import com.sparrowwallet.sparrow.event.CormorantScanStatusEvent;
|
||||||
import com.sparrowwallet.sparrow.event.CormorantSyncStatusEvent;
|
import com.sparrowwallet.sparrow.event.CormorantSyncStatusEvent;
|
||||||
import com.sparrowwallet.sparrow.io.Config;
|
import com.sparrowwallet.sparrow.io.Config;
|
||||||
import com.sparrowwallet.sparrow.net.Bwt;
|
import com.sparrowwallet.sparrow.net.Bwt;
|
||||||
|
import com.sparrowwallet.sparrow.net.ConfigurationException;
|
||||||
import com.sparrowwallet.sparrow.net.CoreAuthType;
|
import com.sparrowwallet.sparrow.net.CoreAuthType;
|
||||||
import com.sparrowwallet.sparrow.net.cormorant.Cormorant;
|
import com.sparrowwallet.sparrow.net.cormorant.Cormorant;
|
||||||
import com.sparrowwallet.drongo.address.Address;
|
import com.sparrowwallet.drongo.address.Address;
|
||||||
|
@ -94,8 +95,10 @@ public class BitcoindClient {
|
||||||
Config config = Config.get();
|
Config config = Config.get();
|
||||||
if((config.getCoreAuthType() == CoreAuthType.COOKIE || config.getCoreAuth() == null || config.getCoreAuth().length() < 2) && config.getCoreDataDir() != null) {
|
if((config.getCoreAuthType() == CoreAuthType.COOKIE || config.getCoreAuth() == null || config.getCoreAuth().length() < 2) && config.getCoreDataDir() != null) {
|
||||||
bitcoindTransport = new BitcoindTransport(config.getCoreServer(), CORE_WALLET_NAME, config.getCoreDataDir());
|
bitcoindTransport = new BitcoindTransport(config.getCoreServer(), CORE_WALLET_NAME, config.getCoreDataDir());
|
||||||
} else {
|
} else if(config.getCoreAuth() != null) {
|
||||||
bitcoindTransport = new BitcoindTransport(config.getCoreServer(), CORE_WALLET_NAME, config.getCoreAuth());
|
bitcoindTransport = new BitcoindTransport(config.getCoreServer(), CORE_WALLET_NAME, config.getCoreAuth());
|
||||||
|
} else {
|
||||||
|
throw new ConfigurationException("Bitcoin Core data folder or user and password is required");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.jsonRpcClient = new JsonRpcClient(bitcoindTransport);
|
this.jsonRpcClient = new JsonRpcClient(bitcoindTransport);
|
||||||
|
@ -114,7 +117,7 @@ public class BitcoindClient {
|
||||||
tip = blockHeader.getBlockHeader();
|
tip = blockHeader.getBlockHeader();
|
||||||
timer.schedule(new PollTask(), 5000, 5000);
|
timer.schedule(new PollTask(), 5000, 5000);
|
||||||
|
|
||||||
if(blockchainInfo.initialblockdownload()) {
|
if(blockchainInfo.initialblockdownload() && networkInfo.networkactive()) {
|
||||||
syncingLock.lock();
|
syncingLock.lock();
|
||||||
try {
|
try {
|
||||||
syncing = true;
|
syncing = true;
|
||||||
|
|
|
@ -10,7 +10,7 @@ public record MempoolEntry(int vsize, int ancestorsize, boolean bip125_replaceab
|
||||||
}
|
}
|
||||||
|
|
||||||
public TxEntry getTxEntry(String txid) {
|
public TxEntry getTxEntry(String txid) {
|
||||||
return new TxEntry(hasUnconfirmedParents() ? -1 : 0, 0, txid);
|
return new TxEntry(hasUnconfirmedParents() ? -1 : 0, 0, txid, fees().base());
|
||||||
}
|
}
|
||||||
|
|
||||||
public VsizeFeerate getVsizeFeerate() {
|
public VsizeFeerate getVsizeFeerate() {
|
||||||
|
|
|
@ -3,6 +3,6 @@ package com.sparrowwallet.sparrow.net.cormorant.bitcoind;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
public record NetworkInfo(int version, String subversion) {
|
public record NetworkInfo(int version, String subversion, boolean networkactive) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ public class ElectrumServerService {
|
||||||
|
|
||||||
@JsonRpcMethod("server.banner")
|
@JsonRpcMethod("server.banner")
|
||||||
public String getServerBanner() {
|
public String getServerBanner() {
|
||||||
return Cormorant.SERVER_NAME + " " + SparrowWallet.APP_VERSION + "\n" + bitcoindClient.getNetworkInfo().subversion();
|
return Cormorant.SERVER_NAME + " " + SparrowWallet.APP_VERSION + "\n" + bitcoindClient.getNetworkInfo().subversion() + (bitcoindClient.getNetworkInfo().networkactive() ? "" : " (disconnected)");
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonRpcMethod("blockchain.estimatefee")
|
@JsonRpcMethod("blockchain.estimatefee")
|
||||||
|
|
|
@ -35,7 +35,7 @@ public class Store {
|
||||||
mempoolEntries.put(txid, null);
|
mempoolEntries.put(txid, null);
|
||||||
}
|
}
|
||||||
entries.removeIf(txe -> txe.height > 0 && txe.tx_hash.equals(listTransaction.txid()));
|
entries.removeIf(txe -> txe.height > 0 && txe.tx_hash.equals(listTransaction.txid()));
|
||||||
txEntry = new TxEntry(0, 0, listTransaction.txid());
|
txEntry = new TxEntry(0, 0, listTransaction.txid(), listTransaction.fee());
|
||||||
} else {
|
} else {
|
||||||
mempoolEntries.remove(txid);
|
mempoolEntries.remove(txid);
|
||||||
entries.removeIf(txe -> txe.height != listTransaction.blockheight() && txe.tx_hash.equals(listTransaction.txid()));
|
entries.removeIf(txe -> txe.height != listTransaction.blockheight() && txe.tx_hash.equals(listTransaction.txid()));
|
||||||
|
|
|
@ -1,14 +1,29 @@
|
||||||
package com.sparrowwallet.sparrow.net.cormorant.index;
|
package com.sparrowwallet.sparrow.net.cormorant.index;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.sparrowwallet.drongo.protocol.Transaction;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
public class TxEntry implements Comparable<TxEntry> {
|
public class TxEntry implements Comparable<TxEntry> {
|
||||||
public final int height;
|
public final int height;
|
||||||
private final transient int index;
|
private final transient int index;
|
||||||
public final String tx_hash;
|
public final String tx_hash;
|
||||||
|
public final Long fee;
|
||||||
|
|
||||||
public TxEntry(int height, int index, String tx_hash) {
|
public TxEntry(int height, int index, String tx_hash) {
|
||||||
this.height = height;
|
this.height = height;
|
||||||
this.index = index;
|
this.index = index;
|
||||||
this.tx_hash = tx_hash;
|
this.tx_hash = tx_hash;
|
||||||
|
this.fee = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TxEntry(int height, int index, String tx_hash, double btcFee) {
|
||||||
|
this.height = height;
|
||||||
|
this.index = index;
|
||||||
|
this.tx_hash = tx_hash;
|
||||||
|
this.fee = btcFee > 0.0 ? (long)(btcFee * Transaction.SATOSHIS_PER_BITCOIN) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -16,22 +31,18 @@ public class TxEntry implements Comparable<TxEntry> {
|
||||||
if(this == o) {
|
if(this == o) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if(o == null || getClass() != o.getClass()) {
|
if(!(o instanceof TxEntry txEntry)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
TxEntry txEntry = (TxEntry) o;
|
return height == txEntry.height && tx_hash.equals(txEntry.tx_hash) && Objects.equals(fee, txEntry.fee);
|
||||||
|
|
||||||
if(height != txEntry.height) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return tx_hash.equals(txEntry.tx_hash);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result = height;
|
int result = height;
|
||||||
result = 31 * result + tx_hash.hashCode();
|
result = 31 * result + tx_hash.hashCode();
|
||||||
|
result = 31 * result + Objects.hashCode(fee);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +73,7 @@ public class TxEntry implements Comparable<TxEntry> {
|
||||||
"height=" + height +
|
"height=" + height +
|
||||||
", index=" + index +
|
", index=" + index +
|
||||||
", tx_hash='" + tx_hash + '\'' +
|
", tx_hash='" + tx_hash + '\'' +
|
||||||
|
", fee=" + fee +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -877,12 +877,14 @@ public class SendController extends WalletFormController implements Initializabl
|
||||||
walletTransaction.getSelectedUtxos().keySet().stream().filter(ref -> ref.getHeight() <= 0)
|
walletTransaction.getSelectedUtxos().keySet().stream().filter(ref -> ref.getHeight() <= 0)
|
||||||
.map(ref -> getWalletForm().getWallet().getWalletTransaction(ref.getHash()))
|
.map(ref -> getWalletForm().getWallet().getWalletTransaction(ref.getHash()))
|
||||||
.filter(Objects::nonNull).distinct().collect(Collectors.toList());
|
.filter(Objects::nonNull).distinct().collect(Collectors.toList());
|
||||||
if(!unconfirmedUtxoTxs.isEmpty()) {
|
if(!unconfirmedUtxoTxs.isEmpty() && unconfirmedUtxoTxs.stream().allMatch(blkTx -> blkTx.getFee() != null && blkTx.getFee() > 0)) {
|
||||||
long utxoTxFee = unconfirmedUtxoTxs.stream().mapToLong(BlockTransaction::getFee).sum();
|
long utxoTxFee = unconfirmedUtxoTxs.stream().mapToLong(BlockTransaction::getFee).sum();
|
||||||
double utxoTxSize = unconfirmedUtxoTxs.stream().mapToDouble(blkTx -> blkTx.getTransaction().getVirtualSize()).sum();
|
double utxoTxSize = unconfirmedUtxoTxs.stream().mapToDouble(blkTx -> blkTx.getTransaction().getVirtualSize()).sum();
|
||||||
long thisFee = walletTransaction.getFee();
|
long thisFee = walletTransaction.getFee();
|
||||||
double thisSize = walletTransaction.getTransaction().getVirtualSize();
|
double thisSize = walletTransaction.getTransaction().getVirtualSize();
|
||||||
|
double thisRate = thisFee / thisSize;
|
||||||
double effectiveRate = (utxoTxFee + thisFee) / (utxoTxSize + thisSize);
|
double effectiveRate = (utxoTxFee + thisFee) / (utxoTxSize + thisSize);
|
||||||
|
if(thisRate > effectiveRate) {
|
||||||
UnitFormat format = Config.get().getUnitFormat() == null ? UnitFormat.DOT : Config.get().getUnitFormat();
|
UnitFormat format = Config.get().getUnitFormat() == null ? UnitFormat.DOT : Config.get().getUnitFormat();
|
||||||
String strEffectiveRate = format.getCurrencyFormat().format(effectiveRate);
|
String strEffectiveRate = format.getCurrencyFormat().format(effectiveRate);
|
||||||
Tooltip tooltip = new Tooltip("CPFP (Child Pays For Parent)\n" + strEffectiveRate + " sats/vB effective rate");
|
Tooltip tooltip = new Tooltip("CPFP (Child Pays For Parent)\n" + strEffectiveRate + " sats/vB effective rate");
|
||||||
|
@ -892,6 +894,9 @@ public class SendController extends WalletFormController implements Initializabl
|
||||||
} else {
|
} else {
|
||||||
cpfpFeeRate.setVisible(false);
|
cpfpFeeRate.setVisible(false);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
cpfpFeeRate.setVisible(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setFeeRatePriority(Double feeRateAmt) {
|
private void setFeeRatePriority(Double feeRateAmt) {
|
||||||
|
|
Loading…
Reference in a new issue