mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-24 12:46:45 +00:00
upgrade to whirlpool-client 0.23.30-early4 + extlibj 0.0.19-dsk3
This commit is contained in:
parent
37c4ff4dd7
commit
fec45356a2
5 changed files with 164 additions and 153 deletions
|
@ -395,25 +395,28 @@ extraJavaModuleInfo {
|
||||||
requires('com.fasterxml.jackson.databind')
|
requires('com.fasterxml.jackson.databind')
|
||||||
requires('logback.classic')
|
requires('logback.classic')
|
||||||
requires('org.json')
|
requires('org.json')
|
||||||
exports('com.sparrowwallet.nightjar')
|
|
||||||
exports('com.samourai.http.client')
|
exports('com.samourai.http.client')
|
||||||
exports('com.samourai.tor.client')
|
exports('com.samourai.tor.client')
|
||||||
exports('com.samourai.wallet.api.backend')
|
exports('com.samourai.wallet.api.backend')
|
||||||
exports('com.samourai.wallet.api.backend.beans')
|
exports('com.samourai.wallet.api.backend.beans')
|
||||||
exports('com.samourai.wallet.hd')
|
exports('com.samourai.wallet.hd')
|
||||||
exports('com.samourai.wallet.hd.java')
|
|
||||||
exports('com.samourai.whirlpool.client.event')
|
exports('com.samourai.whirlpool.client.event')
|
||||||
exports('com.samourai.whirlpool.client.wallet')
|
exports('com.samourai.whirlpool.client.wallet')
|
||||||
exports('com.samourai.whirlpool.client.wallet.beans')
|
exports('com.samourai.whirlpool.client.wallet.beans')
|
||||||
|
exports('com.samourai.whirlpool.client.wallet.data.dataSource')
|
||||||
|
exports('com.samourai.whirlpool.client.wallet.data.dataPersister')
|
||||||
exports('com.samourai.whirlpool.client.whirlpool')
|
exports('com.samourai.whirlpool.client.whirlpool')
|
||||||
exports('com.samourai.whirlpool.client.whirlpool.beans')
|
exports('com.samourai.whirlpool.client.whirlpool.beans')
|
||||||
exports('com.samourai.whirlpool.client.wallet.data.pool')
|
exports('com.samourai.whirlpool.client.wallet.data.pool')
|
||||||
exports('com.samourai.whirlpool.client.wallet.data.utxo')
|
exports('com.samourai.whirlpool.client.wallet.data.utxo')
|
||||||
|
exports('com.samourai.whirlpool.client.wallet.data.utxoConfig')
|
||||||
|
exports('com.samourai.whirlpool.client.wallet.data.supplier')
|
||||||
exports('com.samourai.whirlpool.client.mix.listener')
|
exports('com.samourai.whirlpool.client.mix.listener')
|
||||||
exports('com.samourai.whirlpool.protocol.beans')
|
exports('com.samourai.whirlpool.protocol.beans')
|
||||||
exports('com.samourai.whirlpool.protocol.rest')
|
exports('com.samourai.whirlpool.protocol.rest')
|
||||||
exports('com.samourai.whirlpool.client.tx0')
|
exports('com.samourai.whirlpool.client.tx0')
|
||||||
exports('com.samourai.wallet.segwit.bech32')
|
exports('com.samourai.wallet.segwit.bech32')
|
||||||
|
exports('com.samourai.whirlpool.client.wallet.data.wallet')
|
||||||
exports('com.samourai.whirlpool.client.wallet.data.minerFee')
|
exports('com.samourai.whirlpool.client.wallet.data.minerFee')
|
||||||
exports('com.samourai.whirlpool.client.wallet.data.walletState')
|
exports('com.samourai.whirlpool.client.wallet.data.walletState')
|
||||||
exports('com.sparrowwallet.nightjar.http')
|
exports('com.sparrowwallet.nightjar.http')
|
||||||
|
|
|
@ -455,8 +455,8 @@ public class AppServices {
|
||||||
public Whirlpool getWhirlpool(String walletId) {
|
public Whirlpool getWhirlpool(String walletId) {
|
||||||
Whirlpool whirlpool = whirlpoolMap.get(walletId);
|
Whirlpool whirlpool = whirlpoolMap.get(walletId);
|
||||||
if(whirlpool == null) {
|
if(whirlpool == null) {
|
||||||
HostAndPort torProxy = AppServices.isTorRunning() ? HostAndPort.fromParts("localhost", TorService.PROXY_PORT) : (Config.get().getProxyServer().isEmpty() || !Config.get().isUseProxy() ? null : HostAndPort.fromString(Config.get().getProxyServer()));
|
HostAndPort torProxy = AppServices.isTorRunning() ? HostAndPort.fromParts("localhost", TorService.PROXY_PORT) : (Config.get().getProxyServer() == null || Config.get().getProxyServer().isEmpty() || !Config.get().isUseProxy() ? null : HostAndPort.fromString(Config.get().getProxyServer()));
|
||||||
whirlpool = new Whirlpool(Network.get(), torProxy, Config.get().getScode(), 1, 15);
|
whirlpool = new Whirlpool(Network.get(), torProxy, Config.get().getScode(), 1);
|
||||||
whirlpoolMap.put(walletId, whirlpool);
|
whirlpoolMap.put(walletId, whirlpool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
package com.sparrowwallet.sparrow.whirlpool;
|
package com.sparrowwallet.sparrow.whirlpool;
|
||||||
|
|
||||||
import com.samourai.wallet.api.backend.BackendApi;
|
|
||||||
import com.samourai.wallet.api.backend.MinerFee;
|
|
||||||
import com.samourai.wallet.api.backend.MinerFeeTarget;
|
import com.samourai.wallet.api.backend.MinerFeeTarget;
|
||||||
import com.samourai.wallet.api.backend.beans.*;
|
import com.samourai.wallet.api.backend.beans.TxsResponse;
|
||||||
|
import com.samourai.wallet.api.backend.beans.UnspentOutput;
|
||||||
|
import com.samourai.wallet.api.backend.beans.WalletResponse;
|
||||||
|
import com.samourai.wallet.hd.HD_Wallet;
|
||||||
|
import com.samourai.whirlpool.client.wallet.WhirlpoolWalletConfig;
|
||||||
|
import com.samourai.whirlpool.client.wallet.data.dataPersister.DataPersister;
|
||||||
|
import com.samourai.whirlpool.client.wallet.data.dataSource.WalletResponseDataSource;
|
||||||
|
import com.samourai.whirlpool.client.wallet.data.minerFee.MinerFeeSupplier;
|
||||||
import com.sparrowwallet.drongo.ExtendedKey;
|
import com.sparrowwallet.drongo.ExtendedKey;
|
||||||
import com.sparrowwallet.drongo.KeyPurpose;
|
import com.sparrowwallet.drongo.KeyPurpose;
|
||||||
import com.sparrowwallet.drongo.Network;
|
import com.sparrowwallet.drongo.Network;
|
||||||
|
@ -21,88 +26,20 @@ import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
public class SparrowDataSource extends WalletResponseDataSource {
|
||||||
public class SparrowBackendApi extends BackendApi {
|
private static final Logger log = LoggerFactory.getLogger(SparrowDataSource.class);
|
||||||
private static final Logger log = LoggerFactory.getLogger(SparrowBackendApi.class);
|
|
||||||
private static final int FALLBACK_FEE_RATE = 75;
|
|
||||||
|
|
||||||
public SparrowBackendApi() {
|
public SparrowDataSource(
|
||||||
super(null, null);
|
WhirlpoolWalletConfig config,
|
||||||
|
HD_Wallet bip44w,
|
||||||
|
String walletIdentifier,
|
||||||
|
DataPersister dataPersister)
|
||||||
|
throws Exception {
|
||||||
|
super(config, bip44w, walletIdentifier, dataPersister);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TxsResponse fetchTxs(String[] zpubs, int page, int count) throws Exception {
|
protected WalletResponse fetchWalletResponse() throws Exception {
|
||||||
List<TxsResponse.Tx> txes = new ArrayList<>();
|
|
||||||
|
|
||||||
for(String zpub : zpubs) {
|
|
||||||
Wallet wallet = getWallet(zpub);
|
|
||||||
if(wallet == null) {
|
|
||||||
log.debug("No wallet for " + zpub + " found");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(BlockTransaction blockTransaction : wallet.getTransactions().values()) {
|
|
||||||
TxsResponse.Tx tx = new TxsResponse.Tx();
|
|
||||||
tx.block_height = blockTransaction.getHeight();
|
|
||||||
tx.hash = blockTransaction.getHashAsString();
|
|
||||||
tx.locktime = blockTransaction.getTransaction().getLocktime();
|
|
||||||
tx.time = blockTransaction.getDate().getTime();
|
|
||||||
tx.version = (int)blockTransaction.getTransaction().getVersion();
|
|
||||||
|
|
||||||
tx.inputs = new TxsResponse.TxInput[blockTransaction.getTransaction().getInputs().size()];
|
|
||||||
for(int i = 0; i < blockTransaction.getTransaction().getInputs().size(); i++) {
|
|
||||||
TransactionInput txInput = blockTransaction.getTransaction().getInputs().get(i);
|
|
||||||
tx.inputs[i] = new TxsResponse.TxInput();
|
|
||||||
tx.inputs[i].vin = txInput.getIndex();
|
|
||||||
tx.inputs[i].sequence = txInput.getSequenceNumber();
|
|
||||||
tx.inputs[i].prev_out = new TxsResponse.TxOut();
|
|
||||||
tx.inputs[i].prev_out.txid = txInput.getOutpoint().getHash().toString();
|
|
||||||
tx.inputs[i].prev_out.vout = (int)txInput.getOutpoint().getIndex();
|
|
||||||
|
|
||||||
BlockTransaction spentTransaction = wallet.getTransactions().get(txInput.getOutpoint().getHash());
|
|
||||||
if(spentTransaction != null) {
|
|
||||||
TransactionOutput spentOutput = spentTransaction.getTransaction().getOutputs().get((int)txInput.getOutpoint().getIndex());
|
|
||||||
tx.inputs[i].prev_out.value = spentOutput.getValue();
|
|
||||||
Address[] addresses = spentOutput.getScript().getToAddresses();
|
|
||||||
if(addresses.length > 0) {
|
|
||||||
tx.inputs[i].prev_out.addr = addresses[0].toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tx.out = new TxsResponse.TxOutput[blockTransaction.getTransaction().getOutputs().size()];
|
|
||||||
for(int i = 0; i < blockTransaction.getTransaction().getOutputs().size(); i++) {
|
|
||||||
TransactionOutput txOutput = blockTransaction.getTransaction().getOutputs().get(i);
|
|
||||||
tx.out[i].n = txOutput.getIndex();
|
|
||||||
tx.out[i].value = txOutput.getValue();
|
|
||||||
Address[] addresses = txOutput.getScript().getToAddresses();
|
|
||||||
if(addresses.length > 0) {
|
|
||||||
tx.out[i].addr = addresses[0].toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
txes.add(tx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<TxsResponse.Tx> pageTxes;
|
|
||||||
if(txes.size() < count) {
|
|
||||||
pageTxes = txes;
|
|
||||||
} else {
|
|
||||||
pageTxes = txes.subList(page * count, Math.min((page * count) + count, txes.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
TxsResponse txsResponse = new TxsResponse();
|
|
||||||
txsResponse.n_tx = txes.size();
|
|
||||||
txsResponse.page = page;
|
|
||||||
txsResponse.n_tx_page = pageTxes.size();
|
|
||||||
txsResponse.txs = pageTxes.toArray(new TxsResponse.Tx[0]);
|
|
||||||
|
|
||||||
return txsResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WalletResponse fetchWallet(String[] zpubs) throws Exception {
|
|
||||||
WalletResponse walletResponse = new WalletResponse();
|
WalletResponse walletResponse = new WalletResponse();
|
||||||
walletResponse.wallet = new WalletResponse.Wallet();
|
walletResponse.wallet = new WalletResponse.Wallet();
|
||||||
|
|
||||||
|
@ -113,6 +50,7 @@ public class SparrowBackendApi extends BackendApi {
|
||||||
List<UnspentOutput> unspentOutputs = new ArrayList<>();
|
List<UnspentOutput> unspentOutputs = new ArrayList<>();
|
||||||
int storedBlockHeight = 0;
|
int storedBlockHeight = 0;
|
||||||
|
|
||||||
|
String[] zpubs = getWalletSupplier().getPubs(true);
|
||||||
for(String zpub : zpubs) {
|
for(String zpub : zpubs) {
|
||||||
Wallet wallet = getWallet(zpub);
|
Wallet wallet = getWallet(zpub);
|
||||||
if(wallet == null) {
|
if(wallet == null) {
|
||||||
|
@ -197,22 +135,12 @@ public class SparrowBackendApi extends BackendApi {
|
||||||
|
|
||||||
walletResponse.info.fees = new LinkedHashMap<>();
|
walletResponse.info.fees = new LinkedHashMap<>();
|
||||||
for(MinerFeeTarget target : MinerFeeTarget.values()) {
|
for(MinerFeeTarget target : MinerFeeTarget.values()) {
|
||||||
walletResponse.info.fees.put(target.getValue(), AppServices.getTargetBlockFeeRates() == null ? FALLBACK_FEE_RATE : getMinimumFeeForTarget(Integer.parseInt(target.getValue())));
|
walletResponse.info.fees.put(target.getValue(), getMinerFeeSupplier().getFee(target));
|
||||||
}
|
}
|
||||||
|
|
||||||
return walletResponse;
|
return walletResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public MinerFee fetchMinerFee() throws Exception {
|
|
||||||
Map<String, Integer> fees = new LinkedHashMap<>();
|
|
||||||
for(MinerFeeTarget target : MinerFeeTarget.values()) {
|
|
||||||
fees.put(target.getValue(), AppServices.getTargetBlockFeeRates() == null ? FALLBACK_FEE_RATE : getMinimumFeeForTarget(Integer.parseInt(target.getValue())));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new MinerFee(fees);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void pushTx(String txHex) throws Exception {
|
public void pushTx(String txHex) throws Exception {
|
||||||
Transaction transaction = new Transaction(Utils.hexToBytes(txHex));
|
Transaction transaction = new Transaction(Utils.hexToBytes(txHex));
|
||||||
|
@ -221,25 +149,79 @@ public class SparrowBackendApi extends BackendApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean testConnectivity() {
|
public TxsResponse fetchTxs(String[] zpubs, int page, int count) throws Exception {
|
||||||
return AppServices.isConnected();
|
List<TxsResponse.Tx> txes = new ArrayList<>();
|
||||||
}
|
|
||||||
|
|
||||||
private Integer getMinimumFeeForTarget(int targetBlocks) {
|
for(String zpub : zpubs) {
|
||||||
List<Map.Entry<Integer, Double>> feeRates = new ArrayList<>(AppServices.getTargetBlockFeeRates().entrySet());
|
Wallet wallet = getWallet(zpub);
|
||||||
Collections.reverse(feeRates);
|
if(wallet == null) {
|
||||||
for(Map.Entry<Integer, Double> feeRate : feeRates) {
|
log.debug("No wallet for " + zpub + " found");
|
||||||
if(feeRate.getKey() <= targetBlocks) {
|
continue;
|
||||||
return feeRate.getValue().intValue();
|
}
|
||||||
|
|
||||||
|
for(BlockTransaction blockTransaction : wallet.getTransactions().values()) {
|
||||||
|
TxsResponse.Tx tx = new TxsResponse.Tx();
|
||||||
|
tx.block_height = blockTransaction.getHeight();
|
||||||
|
tx.hash = blockTransaction.getHashAsString();
|
||||||
|
tx.locktime = blockTransaction.getTransaction().getLocktime();
|
||||||
|
tx.time = blockTransaction.getDate().getTime();
|
||||||
|
tx.version = (int)blockTransaction.getTransaction().getVersion();
|
||||||
|
|
||||||
|
tx.inputs = new TxsResponse.TxInput[blockTransaction.getTransaction().getInputs().size()];
|
||||||
|
for(int i = 0; i < blockTransaction.getTransaction().getInputs().size(); i++) {
|
||||||
|
TransactionInput txInput = blockTransaction.getTransaction().getInputs().get(i);
|
||||||
|
tx.inputs[i] = new TxsResponse.TxInput();
|
||||||
|
tx.inputs[i].vin = txInput.getIndex();
|
||||||
|
tx.inputs[i].sequence = txInput.getSequenceNumber();
|
||||||
|
tx.inputs[i].prev_out = new TxsResponse.TxOut();
|
||||||
|
tx.inputs[i].prev_out.txid = txInput.getOutpoint().getHash().toString();
|
||||||
|
tx.inputs[i].prev_out.vout = (int)txInput.getOutpoint().getIndex();
|
||||||
|
|
||||||
|
BlockTransaction spentTransaction = wallet.getTransactions().get(txInput.getOutpoint().getHash());
|
||||||
|
if(spentTransaction != null) {
|
||||||
|
TransactionOutput spentOutput = spentTransaction.getTransaction().getOutputs().get((int)txInput.getOutpoint().getIndex());
|
||||||
|
tx.inputs[i].prev_out.value = spentOutput.getValue();
|
||||||
|
Address[] addresses = spentOutput.getScript().getToAddresses();
|
||||||
|
if(addresses.length > 0) {
|
||||||
|
tx.inputs[i].prev_out.addr = addresses[0].toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tx.out = new TxsResponse.TxOutput[blockTransaction.getTransaction().getOutputs().size()];
|
||||||
|
for(int i = 0; i < blockTransaction.getTransaction().getOutputs().size(); i++) {
|
||||||
|
TransactionOutput txOutput = blockTransaction.getTransaction().getOutputs().get(i);
|
||||||
|
tx.out[i].n = txOutput.getIndex();
|
||||||
|
tx.out[i].value = txOutput.getValue();
|
||||||
|
Address[] addresses = txOutput.getScript().getToAddresses();
|
||||||
|
if(addresses.length > 0) {
|
||||||
|
tx.out[i].addr = addresses[0].toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
txes.add(tx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return feeRates.get(0).getValue().intValue();
|
List<TxsResponse.Tx> pageTxes;
|
||||||
|
if(txes.size() < count) {
|
||||||
|
pageTxes = txes;
|
||||||
|
} else {
|
||||||
|
pageTxes = txes.subList(page * count, Math.min((page * count) + count, txes.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TxsResponse txsResponse = new TxsResponse();
|
||||||
|
txsResponse.n_tx = txes.size();
|
||||||
|
txsResponse.page = page;
|
||||||
|
txsResponse.n_tx_page = pageTxes.size();
|
||||||
|
txsResponse.txs = pageTxes.toArray(new TxsResponse.Tx[0]);
|
||||||
|
|
||||||
|
return txsResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initBip84(String zpub) throws Exception {
|
public MinerFeeSupplier getMinerFeeSupplier() {
|
||||||
//nothing required
|
return SparrowMinerFeeSupplier.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Wallet getWallet(String zpub) {
|
private Wallet getWallet(String zpub) {
|
||||||
|
@ -254,24 +236,4 @@ public class SparrowBackendApi extends BackendApi {
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<UnspentOutput> fetchUtxos(String zpub) throws Exception {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<UnspentOutput> fetchUtxos(String[] zpubs) throws Exception {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, MultiAddrResponse.Address> fetchAddresses(String[] zpubs) throws Exception {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MultiAddrResponse.Address fetchAddress(String zpub) throws Exception {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,11 +1,46 @@
|
||||||
package com.sparrowwallet.sparrow.whirlpool;
|
package com.sparrowwallet.sparrow.whirlpool;
|
||||||
|
|
||||||
import com.samourai.wallet.api.backend.MinerFee;
|
import com.samourai.wallet.api.backend.MinerFeeTarget;
|
||||||
import com.samourai.whirlpool.client.wallet.data.minerFee.MinerFeeSupplier;
|
import com.samourai.whirlpool.client.wallet.data.minerFee.MinerFeeSupplier;
|
||||||
|
import com.sparrowwallet.sparrow.AppServices;
|
||||||
|
|
||||||
public class SparrowMinerFeeSupplier extends MinerFeeSupplier {
|
import java.util.ArrayList;
|
||||||
public SparrowMinerFeeSupplier(int feeMin, int feeMax, int feeFallback, MinerFee currentMinerFee) {
|
import java.util.Collections;
|
||||||
super(feeMin, feeMax, feeFallback);
|
import java.util.List;
|
||||||
setValue(currentMinerFee);
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class SparrowMinerFeeSupplier implements MinerFeeSupplier {
|
||||||
|
private static final int FALLBACK_FEE_RATE = 75;
|
||||||
|
|
||||||
|
public static SparrowMinerFeeSupplier instance;
|
||||||
|
|
||||||
|
public static SparrowMinerFeeSupplier getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new SparrowMinerFeeSupplier();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SparrowMinerFeeSupplier() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getFee(MinerFeeTarget feeTarget) {
|
||||||
|
if (AppServices.getTargetBlockFeeRates() == null) {
|
||||||
|
return FALLBACK_FEE_RATE;
|
||||||
|
}
|
||||||
|
return getMinimumFeeForTarget(Integer.parseInt(feeTarget.getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer getMinimumFeeForTarget(int targetBlocks) {
|
||||||
|
List<Map.Entry<Integer, Double>> feeRates = new ArrayList<>(AppServices.getTargetBlockFeeRates().entrySet());
|
||||||
|
Collections.reverse(feeRates);
|
||||||
|
for(Map.Entry<Integer, Double> feeRate : feeRates) {
|
||||||
|
if(feeRate.getKey() <= targetBlocks) {
|
||||||
|
return feeRate.getValue().intValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return feeRates.get(0).getValue().intValue();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,17 +3,25 @@ package com.sparrowwallet.sparrow.whirlpool;
|
||||||
import com.google.common.eventbus.Subscribe;
|
import com.google.common.eventbus.Subscribe;
|
||||||
import com.google.common.net.HostAndPort;
|
import com.google.common.net.HostAndPort;
|
||||||
import com.samourai.tor.client.TorClientService;
|
import com.samourai.tor.client.TorClientService;
|
||||||
import com.samourai.wallet.api.backend.BackendApi;
|
|
||||||
import com.samourai.wallet.api.backend.beans.UnspentOutput;
|
import com.samourai.wallet.api.backend.beans.UnspentOutput;
|
||||||
import com.samourai.wallet.hd.HD_Wallet;
|
import com.samourai.wallet.hd.HD_Wallet;
|
||||||
import com.samourai.wallet.hd.java.HD_WalletFactoryJava;
|
import com.samourai.wallet.hd.HD_WalletFactoryGeneric;
|
||||||
import com.samourai.whirlpool.client.event.*;
|
import com.samourai.whirlpool.client.event.MixFailEvent;
|
||||||
|
import com.samourai.whirlpool.client.event.MixSuccessEvent;
|
||||||
|
import com.samourai.whirlpool.client.event.WalletStartEvent;
|
||||||
|
import com.samourai.whirlpool.client.event.WalletStopEvent;
|
||||||
import com.samourai.whirlpool.client.tx0.*;
|
import com.samourai.whirlpool.client.tx0.*;
|
||||||
import com.samourai.whirlpool.client.wallet.WhirlpoolEventService;
|
import com.samourai.whirlpool.client.wallet.WhirlpoolEventService;
|
||||||
import com.samourai.whirlpool.client.wallet.WhirlpoolWallet;
|
import com.samourai.whirlpool.client.wallet.WhirlpoolWallet;
|
||||||
import com.samourai.whirlpool.client.wallet.WhirlpoolWalletConfig;
|
import com.samourai.whirlpool.client.wallet.WhirlpoolWalletConfig;
|
||||||
import com.samourai.whirlpool.client.wallet.WhirlpoolWalletService;
|
import com.samourai.whirlpool.client.wallet.WhirlpoolWalletService;
|
||||||
import com.samourai.whirlpool.client.wallet.beans.*;
|
import com.samourai.whirlpool.client.wallet.beans.Tx0FeeTarget;
|
||||||
|
import com.samourai.whirlpool.client.wallet.beans.WhirlpoolAccount;
|
||||||
|
import com.samourai.whirlpool.client.wallet.beans.WhirlpoolServer;
|
||||||
|
import com.samourai.whirlpool.client.wallet.beans.WhirlpoolUtxo;
|
||||||
|
import com.samourai.whirlpool.client.wallet.data.dataPersister.DataPersisterFactory;
|
||||||
|
import com.samourai.whirlpool.client.wallet.data.dataPersister.FileDataPersister;
|
||||||
|
import com.samourai.whirlpool.client.wallet.data.dataSource.DataSourceFactory;
|
||||||
import com.samourai.whirlpool.client.wallet.data.pool.PoolData;
|
import com.samourai.whirlpool.client.wallet.data.pool.PoolData;
|
||||||
import com.samourai.whirlpool.client.wallet.data.utxo.UtxoSupplier;
|
import com.samourai.whirlpool.client.wallet.data.utxo.UtxoSupplier;
|
||||||
import com.samourai.whirlpool.client.whirlpool.ServerApi;
|
import com.samourai.whirlpool.client.whirlpool.ServerApi;
|
||||||
|
@ -36,7 +44,9 @@ import javafx.concurrent.Task;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class Whirlpool {
|
public class Whirlpool {
|
||||||
|
@ -51,26 +61,27 @@ public class Whirlpool {
|
||||||
private final WhirlpoolWalletConfig config;
|
private final WhirlpoolWalletConfig config;
|
||||||
private HD_Wallet hdWallet;
|
private HD_Wallet hdWallet;
|
||||||
|
|
||||||
public Whirlpool(Network network, HostAndPort torProxy, String sCode, int maxClients, int clientDelay) {
|
public Whirlpool(Network network, HostAndPort torProxy, String sCode, int maxClients) {
|
||||||
this.torProxy = torProxy;
|
this.torProxy = torProxy;
|
||||||
this.whirlpoolServer = WhirlpoolServer.valueOf(network.getName().toUpperCase());
|
this.whirlpoolServer = WhirlpoolServer.valueOf(network.getName().toUpperCase());
|
||||||
this.httpClientService = new JavaHttpClientService(torProxy);
|
this.httpClientService = new JavaHttpClientService(torProxy);
|
||||||
this.stompClientService = new JavaStompClientService(httpClientService);
|
this.stompClientService = new JavaStompClientService(httpClientService);
|
||||||
this.torClientService = new WhirlpoolTorClientService();
|
this.torClientService = new WhirlpoolTorClientService();
|
||||||
this.whirlpoolWalletService = new WhirlpoolWalletService();
|
|
||||||
this.config = computeWhirlpoolWalletConfig(sCode, maxClients, clientDelay);
|
DataPersisterFactory dataPersisterFactory = (config, bip44w, walletIdentifier) -> new FileDataPersister(config, bip44w, walletIdentifier);
|
||||||
|
DataSourceFactory dataSourceFactory = (config, bip44w, walletIdentifier, dataPersister) -> new SparrowDataSource(config, bip44w, walletIdentifier, dataPersister);
|
||||||
|
this.whirlpoolWalletService = new WhirlpoolWalletService(dataPersisterFactory, dataSourceFactory);
|
||||||
|
this.config = computeWhirlpoolWalletConfig(sCode, maxClients);
|
||||||
|
|
||||||
WhirlpoolEventService.getInstance().register(this);
|
WhirlpoolEventService.getInstance().register(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private WhirlpoolWalletConfig computeWhirlpoolWalletConfig(String sCode, int maxClients, int clientDelay) {
|
private WhirlpoolWalletConfig computeWhirlpoolWalletConfig(String sCode, int maxClients) {
|
||||||
boolean onion = (torProxy != null);
|
boolean onion = (torProxy != null);
|
||||||
String serverUrl = whirlpoolServer.getServerUrl(onion);
|
String serverUrl = whirlpoolServer.getServerUrl(onion);
|
||||||
|
|
||||||
ServerApi serverApi = new ServerApi(serverUrl, httpClientService);
|
ServerApi serverApi = new ServerApi(serverUrl, httpClientService);
|
||||||
BackendApi backendApi = new SparrowBackendApi();
|
|
||||||
|
|
||||||
WhirlpoolWalletConfig whirlpoolWalletConfig = new WhirlpoolWalletConfig(httpClientService, stompClientService, torClientService, serverApi, whirlpoolServer, false, backendApi);
|
WhirlpoolWalletConfig whirlpoolWalletConfig = new WhirlpoolWalletConfig(httpClientService, stompClientService, torClientService, serverApi, whirlpoolServer.getParams(), false);
|
||||||
whirlpoolWalletConfig.setScode(sCode);
|
whirlpoolWalletConfig.setScode(sCode);
|
||||||
|
|
||||||
return whirlpoolWalletConfig;
|
return whirlpoolWalletConfig;
|
||||||
|
@ -114,7 +125,7 @@ public class Whirlpool {
|
||||||
|
|
||||||
private Tx0ParamService getTx0ParamService() {
|
private Tx0ParamService getTx0ParamService() {
|
||||||
try {
|
try {
|
||||||
SparrowMinerFeeSupplier minerFeeSupplier = new SparrowMinerFeeSupplier(config.getFeeMin(), config.getFeeMax(), config.getFeeFallback(), config.getBackendApi().fetchMinerFee());
|
SparrowMinerFeeSupplier minerFeeSupplier = SparrowMinerFeeSupplier.getInstance();
|
||||||
return new Tx0ParamService(minerFeeSupplier, config);
|
return new Tx0ParamService(minerFeeSupplier, config);
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
log.error("Error fetching miner fees", e);
|
log.error("Error fetching miner fees", e);
|
||||||
|
@ -134,17 +145,17 @@ public class Whirlpool {
|
||||||
int purpose = scriptType.getDefaultDerivation().get(0).num();
|
int purpose = scriptType.getDefaultDerivation().get(0).num();
|
||||||
List<String> words = keystore.getSeed().getMnemonicCode();
|
List<String> words = keystore.getSeed().getMnemonicCode();
|
||||||
String passphrase = keystore.getSeed().getPassphrase().asString();
|
String passphrase = keystore.getSeed().getPassphrase().asString();
|
||||||
HD_WalletFactoryJava hdWalletFactory = HD_WalletFactoryJava.getInstance();
|
HD_WalletFactoryGeneric hdWalletFactory = HD_WalletFactoryGeneric.getInstance();
|
||||||
byte[] seed = hdWalletFactory.computeSeedFromWords(words);
|
byte[] seed = hdWalletFactory.computeSeedFromWords(words);
|
||||||
hdWallet = new HD_Wallet(purpose, words, whirlpoolServer, seed, passphrase, 1);
|
hdWallet = new HD_Wallet(purpose, words, config.getNetworkParameters(), seed, passphrase, 1);
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
throw new IllegalStateException("Could not create Whirlpool HD wallet ", e);
|
throw new IllegalStateException("Could not create Whirlpool HD wallet ", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public WhirlpoolWallet getWhirlpoolWallet() throws WhirlpoolException {
|
public WhirlpoolWallet getWhirlpoolWallet() throws WhirlpoolException {
|
||||||
if(whirlpoolWalletService.whirlpoolWallet() != null) {
|
if(whirlpoolWalletService.getWhirlpoolWalletOrNull() != null) {
|
||||||
return whirlpoolWalletService.whirlpoolWallet();
|
return whirlpoolWalletService.getWhirlpoolWalletOrNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(hdWallet == null) {
|
if(hdWallet == null) {
|
||||||
|
@ -167,11 +178,11 @@ public class Whirlpool {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isStarted() {
|
public boolean isStarted() {
|
||||||
if(whirlpoolWalletService.whirlpoolWallet() == null) {
|
if(whirlpoolWalletService.getWhirlpoolWalletOrNull() == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return whirlpoolWalletService.whirlpoolWallet().isStarted();
|
return whirlpoolWalletService.getWhirlpoolWalletOrNull().isStarted();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
|
@ -226,7 +237,7 @@ public class Whirlpool {
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onMixFail(MixFailEvent e) {
|
public void onMixFail(MixFailEvent e) {
|
||||||
log.info("Mix failed for utxo " + e.getWhirlpoolUtxo().getUtxo().tx_hash + ":" + e.getWhirlpoolUtxo().getUtxo().tx_output_n);
|
log.info("Mix failed for utxo " + e.getMixFail().getWhirlpoolUtxo().getUtxo().tx_hash + ":" + e.getMixFail().getWhirlpoolUtxo().getUtxo().tx_output_n);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
|
|
Loading…
Reference in a new issue