From 6e5ef74dc765865f364c142baf55cc4aca58177d Mon Sep 17 00:00:00 2001 From: Andrea Raspitzu Date: Tue, 1 Oct 2019 11:10:10 +0200 Subject: [PATCH 1/6] Use custom eclair-core with issue fix --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index bfb7221f..580991d3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -110,7 +110,7 @@ dependencies { exclude group: 'ch.qos.logback' } // eclair core - implementation 'fr.acinq.eclair:eclair-core_2.11:0.3.3-android' + implementation 'fr.acinq.eclair:eclair-core_2.11:0.3.4-android-SNAPSHOT' // database orm implementation 'org.greenrobot:greendao:3.2.2' // required for greendao encryption, disabled for now From 0636440f98bd8d66ab16002a4d5cf7b92b12480b Mon Sep 17 00:00:00 2001 From: Andrea Raspitzu Date: Tue, 1 Oct 2019 14:58:43 +0200 Subject: [PATCH 2/6] Use new MilliSatoshi class, don't use Globals (WIP) --- .../main/java/fr/acinq/eclair/wallet/App.java | 51 ++++++++++----- .../BitcoinTransactionDetailsActivity.java | 2 +- .../activities/ChannelDetailsActivity.java | 5 +- .../wallet/activities/HomeActivity.java | 6 +- .../activities/LNPaymentDetailsActivity.java | 2 +- .../activities/NetworkInfosActivity.java | 11 ++-- .../activities/OpenChannelActivity.java | 2 +- .../activities/SendPaymentActivity.java | 35 +++++----- .../wallet/activities/StartupActivity.java | 1 - .../wallet/actors/ElectrumSupervisor.java | 5 +- .../eclair/wallet/actors/NodeSupervisor.java | 65 ++++++++++--------- .../wallet/adapters/LightningErrorHolder.java | 3 +- .../adapters/LocalChannelItemHolder.java | 10 +-- .../wallet/adapters/PaymentItemHolder.java | 4 +- .../wallet/customviews/CoinAmountView.java | 4 +- .../ClosingChannelNotificationEvent.java | 2 +- .../ReceivedLNPaymentNotificationEvent.java | 2 +- .../fragments/ChannelsListFragment.java | 2 +- .../PaymentRequestParametersDialog.java | 10 +-- .../fragments/ReceivePaymentFragment.java | 4 +- .../OpenChannelCapacityFragment.java | 22 +++---- .../OpenChannelLiquidityFragment.java | 10 +-- .../wallet/models/LightningPaymentError.java | 20 +++--- .../eclair/wallet/utils/WalletUtils.java | 10 +-- .../res/layout/fragment_receive_payment.xml | 6 +- 25 files changed, 162 insertions(+), 132 deletions(-) diff --git a/app/src/main/java/fr/acinq/eclair/wallet/App.java b/app/src/main/java/fr/acinq/eclair/wallet/App.java index 72f9049e..bb9a6143 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/App.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/App.java @@ -46,9 +46,11 @@ import fr.acinq.eclair.blockchain.electrum.ElectrumClient; import fr.acinq.eclair.blockchain.electrum.ElectrumEclairWallet; import fr.acinq.eclair.blockchain.electrum.ElectrumWallet; +import fr.acinq.eclair.blockchain.fee.FeeEstimator; import fr.acinq.eclair.channel.*; import fr.acinq.eclair.io.Peer; import fr.acinq.eclair.package$; +import fr.acinq.eclair.payment.PaymentInitiator; import fr.acinq.eclair.payment.PaymentLifecycle; import fr.acinq.eclair.payment.PaymentRequest; import fr.acinq.eclair.router.RouteParams; @@ -71,12 +73,19 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.crypto.digests.SHA256Digest; + +import scala.Function0; +import scala.Function1; +import scala.Int; +import scala.None; import scala.Option; import scala.Symbol; import scala.Tuple2; +import scala.Unit; import scala.collection.Iterable; import scala.collection.Iterator; import scala.collection.Seq; +import scala.collection.Seq$; import scala.concurrent.Await; import scala.concurrent.Future; import scala.concurrent.duration.Duration; @@ -279,24 +288,32 @@ public PaymentRequest generatePaymentRequest(final String description, final Opt * If false, can lead the user to pay a lot of fees. */ public void sendLNPayment(final PaymentRequest paymentRequest, final long amountMsat, final boolean checkFees) { - final Long finalCltvExpiry = paymentRequest.minFinalCltvExpiry().isDefined() && paymentRequest.minFinalCltvExpiry().get() instanceof Long - ? (Long) paymentRequest.minFinalCltvExpiry().get() - : (Long) Channel.MIN_CLTV_EXPIRY(); + final long finalCltvExpiry = paymentRequest.minFinalCltvExpiryDelta().isDefined() ? paymentRequest.minFinalCltvExpiryDelta().get().toInt() : Channel.MIN_CLTV_EXPIRY_DELTA().toInt(); final Option routeParams = checkFees ? Option.apply(null) // when fee protection is enabled, use the default RouteParams with reasonable values : Option.apply(RouteParams.apply( // otherwise, let's build a "no limit" RouteParams false, // never randomize on mobile - fr.acinq.bitcoin.package$.MODULE$.millibtc2millisatoshi(new MilliBtc(BigDecimal.exact(1))).amount(), // at most 1mBTC base fee + MilliSatoshi.toMilliSatoshi(new MilliBtc(BigDecimal.exact(1))), // at most 1mBTC base fee 1d, // at most 100% 4, Router.DEFAULT_ROUTE_MAX_CLTV(), Option.empty())); log.info("(lightning) sending {} msat for invoice {}", amountMsat, paymentRequest.toString()); - appKit.eclairKit.paymentInitiator().tell(new PaymentLifecycle.SendPayment( - amountMsat, paymentRequest.paymentHash(), paymentRequest.nodeId(), paymentRequest.routingInfo(), - finalCltvExpiry + 1, 10, routeParams), ActorRef.noSender()); + PaymentInitiator.SendPaymentRequest spr = new PaymentInitiator.SendPaymentRequest( + new MilliSatoshi(amountMsat), + paymentRequest.paymentHash(), + paymentRequest.nodeId(), + 10, + new CltvExpiryDelta((int) finalCltvExpiry + 1), + Option.apply(paymentRequest), + Option.apply(null), + Seq$.MODULE$.empty(), + paymentRequest.routingInfo(), + routeParams + ); + appKit.eclairKit.paymentInitiator().tell(spr, ActorRef.noSender()); } /** @@ -390,9 +407,9 @@ public Satoshi getAvailableFundsAfterFees(final long feesPerKw) { long available = 0; Iterator it = tx_fee._1.txOut().iterator(); while (it.hasNext()) { - available += it.next().amount().amount(); + available += it.next().amount().toLong(); } - available -= tx_fee._2.amount(); + available -= tx_fee._2.toLong(); return new Satoshi(Math.max(0, available)); } catch (Exception e) { log.error("could not retrieve max available funds after fees", e); @@ -513,17 +530,15 @@ public String nodePublicKey() { return appKit.eclairKit.nodeParams().privateKey().publicKey().toString(); } - public static long estimateSlowFees() { - return Globals.feeratesPerKB() != null && Globals.feeratesPerKB().get() != null ? Math.max(Globals.feeratesPerKB().get().blocks_72() / 1000, 3) : 3; + public long estimateSlowFees() { + return Math.max(appKit.eclairKit.nodeParams().onChainFeeConf().feeEstimator().getFeeratePerKb(72) / 1000, 3); } - public static long estimateMediumFees() { - return Globals.feeratesPerKB() != null && Globals.feeratesPerKB().get() != null ? Math.max(Globals.feeratesPerKB().get().blocks_12() / 1000, estimateSlowFees()) : 18; - } + public long estimateMediumFees() { + return Math.max(appKit.eclairKit.nodeParams().onChainFeeConf().feeEstimator().getFeeratePerKb(12) / 1000, 3); } - public static long estimateFastFees() { - return Globals.feeratesPerKB() != null && Globals.feeratesPerKB().get() != null ? Math.max(Globals.feeratesPerKB().get().blocks_2() / 1000, estimateMediumFees()) : 108; - } + public long estimateFastFees() { + return Math.max(appKit.eclairKit.nodeParams().onChainFeeConf().feeEstimator().getFeeratePerKb(2) / 1000, 3); } /** * Asynchronously asks for the Lightning Network's channels count. Dispatch a {@link NetworkChannelsCountEvent} containing the channel count. @@ -615,7 +630,7 @@ public Satoshi getOnchainBalance() { // if electrum has not send any data, fetch last known onchain balance from DB if (this.electrumState.get() == null || this.electrumState.get().confirmedBalance == null || this.electrumState.get().unconfirmedBalance == null) { - return fr.acinq.bitcoin.package$.MODULE$.millisatoshi2satoshi(new MilliSatoshi(dbHelper.getOnchainBalanceMsat())); + return (new MilliSatoshi(dbHelper.getOnchainBalanceMsat())).truncateToSatoshi(); } else { final Satoshi confirmed = electrumState.get().confirmedBalance; final Satoshi unconfirmed = electrumState.get().unconfirmedBalance; diff --git a/app/src/main/java/fr/acinq/eclair/wallet/activities/BitcoinTransactionDetailsActivity.java b/app/src/main/java/fr/acinq/eclair/wallet/activities/BitcoinTransactionDetailsActivity.java index 2f9e96a3..b197b1a7 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/activities/BitcoinTransactionDetailsActivity.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/activities/BitcoinTransactionDetailsActivity.java @@ -28,7 +28,7 @@ import android.view.View; import android.widget.Toast; import com.google.common.base.Strings; -import fr.acinq.bitcoin.MilliSatoshi; +import fr.acinq.eclair.MilliSatoshi; import fr.acinq.eclair.CoinUnit; import fr.acinq.eclair.CoinUtils; import fr.acinq.eclair.wallet.R; diff --git a/app/src/main/java/fr/acinq/eclair/wallet/activities/ChannelDetailsActivity.java b/app/src/main/java/fr/acinq/eclair/wallet/activities/ChannelDetailsActivity.java index f97cba4c..cebfa595 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/activities/ChannelDetailsActivity.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/activities/ChannelDetailsActivity.java @@ -29,12 +29,11 @@ import android.view.View; import android.widget.Toast; import com.google.common.base.Strings; -import fr.acinq.bitcoin.MilliSatoshi; +import fr.acinq.eclair.MilliSatoshi; import fr.acinq.bitcoin.Satoshi; import fr.acinq.eclair.CoinUnit; import fr.acinq.eclair.CoinUtils; import fr.acinq.eclair.Features; -import fr.acinq.eclair.Globals; import fr.acinq.eclair.channel.*; import fr.acinq.eclair.router.NORMAL$; import fr.acinq.eclair.wallet.R; @@ -219,7 +218,7 @@ private void setupView(final LocalChannel channel, @Nullable final ActorRef chan if (channel.getRefundAtBlock() > 0) { mBinding.closingRefundBlock.setValue(getString(R.string.channeldetails_refund_block_value, NumberFormat.getInstance().format(channel.getRefundAtBlock()), - NumberFormat.getInstance().format(Globals.blockCount().get()))); + NumberFormat.getInstance().format(app.appKit.eclairKit.nodeParams().currentBlockHeight()))); } mBinding.closingRefundBlock.setVisibility(View.VISIBLE); } diff --git a/app/src/main/java/fr/acinq/eclair/wallet/activities/HomeActivity.java b/app/src/main/java/fr/acinq/eclair/wallet/activities/HomeActivity.java index 38c5188d..406cc0b4 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/activities/HomeActivity.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/activities/HomeActivity.java @@ -41,7 +41,7 @@ import android.widget.TextView; import android.widget.Toast; import com.google.android.gms.common.util.Strings; -import fr.acinq.bitcoin.MilliSatoshi; +import fr.acinq.eclair.MilliSatoshi; import fr.acinq.bitcoin.package$; import fr.acinq.eclair.blockchain.electrum.ElectrumClient; import fr.acinq.eclair.blockchain.electrum.ElectrumWallet; @@ -573,8 +573,8 @@ public void handleThrowableEvent(ThrowableFailureEvent event) { private void updateBalance() { final MilliSatoshi lightningBalance = NodeSupervisor.getChannelsBalance(); - final MilliSatoshi walletBalance = app == null ? new MilliSatoshi(0) : package$.MODULE$.satoshi2millisatoshi(app.getOnchainBalance()); - mBinding.balanceTotal.setAmountMsat(new MilliSatoshi(lightningBalance.amount() + walletBalance.amount())); + final MilliSatoshi walletBalance = app == null ? new MilliSatoshi(0) : MilliSatoshi.toMilliSatoshi(app.getOnchainBalance()); + mBinding.balanceTotal.setAmountMsat(new MilliSatoshi(lightningBalance.toLong() + walletBalance.toLong())); mBinding.balanceOnchain.setAmountMsat(walletBalance); mBinding.balanceLightning.setAmountMsat(lightningBalance); } diff --git a/app/src/main/java/fr/acinq/eclair/wallet/activities/LNPaymentDetailsActivity.java b/app/src/main/java/fr/acinq/eclair/wallet/activities/LNPaymentDetailsActivity.java index e667827c..88b8be0d 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/activities/LNPaymentDetailsActivity.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/activities/LNPaymentDetailsActivity.java @@ -27,7 +27,7 @@ import androidx.appcompat.widget.Toolbar; import android.view.View; import com.google.android.gms.common.util.Strings; -import fr.acinq.bitcoin.MilliSatoshi; +import fr.acinq.eclair.MilliSatoshi; import fr.acinq.eclair.CoinUnit; import fr.acinq.eclair.CoinUtils; import fr.acinq.eclair.wallet.R; diff --git a/app/src/main/java/fr/acinq/eclair/wallet/activities/NetworkInfosActivity.java b/app/src/main/java/fr/acinq/eclair/wallet/activities/NetworkInfosActivity.java index 27fee492..c609923d 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/activities/NetworkInfosActivity.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/activities/NetworkInfosActivity.java @@ -38,7 +38,7 @@ import java.text.NumberFormat; import java.util.Date; -import fr.acinq.eclair.Globals; +import fr.acinq.eclair.blockchain.fee.FeeEstimator; import fr.acinq.eclair.wallet.R; import fr.acinq.eclair.wallet.databinding.ActivityNetworkInfosBinding; import fr.acinq.eclair.wallet.events.NetworkChannelsCountEvent; @@ -78,11 +78,12 @@ public void onRefresh() { } private void refreshData() { + Long currentBlockHeight = app.appKit.eclairKit.nodeParams().currentBlockHeight(); if (app.getBlockTimestamp() == 0) { - mBinding.blockCount.setValue(NumberFormat.getInstance().format(Globals.blockCount().get())); + mBinding.blockCount.setValue(NumberFormat.getInstance().format(currentBlockHeight)); } else { mBinding.blockCount.setHtmlValue(getString(R.string.networkinfos_block, - NumberFormat.getInstance().format(Globals.blockCount().get()), // block height + NumberFormat.getInstance().format(currentBlockHeight), // block height DateFormat.getDateTimeInstance().format(new Date(app.getBlockTimestamp() * 1000)))); // block timestamp } @@ -104,8 +105,8 @@ private void refreshData() { } else { mBinding.electrumAddress.setActionLabel(getString(R.string.networkinfos_electrum_address_change_custom)); } - - mBinding.feeRate.setValue(NumberFormat.getInstance().format(Globals.feeratesPerKw().get().block_1()) + " sat/kw"); + FeeEstimator feeEstimator = app.appKit.eclairKit.nodeParams().onChainFeeConf().feeEstimator(); + mBinding.feeRate.setValue(NumberFormat.getInstance().format(feeEstimator.getFeeratePerKw(1)) + " sat/kw"); app.getNetworkChannelsCount(); mBinding.swipeRefresh.setRefreshing(false); } diff --git a/app/src/main/java/fr/acinq/eclair/wallet/activities/OpenChannelActivity.java b/app/src/main/java/fr/acinq/eclair/wallet/activities/OpenChannelActivity.java index 005aa0a6..56adc320 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/activities/OpenChannelActivity.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/activities/OpenChannelActivity.java @@ -26,7 +26,7 @@ import androidx.fragment.app.FragmentManager; import android.view.inputmethod.InputMethodManager; import android.widget.Toast; -import fr.acinq.bitcoin.MilliSatoshi; +import fr.acinq.eclair.MilliSatoshi; import fr.acinq.bitcoin.Satoshi; import fr.acinq.eclair.io.NodeURI; import fr.acinq.eclair.io.Peer; diff --git a/app/src/main/java/fr/acinq/eclair/wallet/activities/SendPaymentActivity.java b/app/src/main/java/fr/acinq/eclair/wallet/activities/SendPaymentActivity.java index d2baaf7a..13c73dae 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/activities/SendPaymentActivity.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/activities/SendPaymentActivity.java @@ -34,12 +34,11 @@ import android.widget.TextView; import com.google.common.base.Strings; import fr.acinq.bitcoin.ByteVector32; -import fr.acinq.bitcoin.MilliSatoshi; +import fr.acinq.eclair.MilliSatoshi; import fr.acinq.bitcoin.Satoshi; import fr.acinq.bitcoin.package$; import fr.acinq.eclair.CoinUnit; import fr.acinq.eclair.CoinUtils; -import fr.acinq.eclair.Globals; import fr.acinq.eclair.payment.PaymentRequest; import fr.acinq.eclair.wallet.App; import fr.acinq.eclair.wallet.BuildConfig; @@ -129,7 +128,7 @@ private boolean checkPaymentRequestValid(final PaymentRequest paymentRequest) { return false; } // check channels balance is sufficient - if (paymentRequest.amount().isDefined() && !NodeSupervisor.hasNormalChannelsWithBalance(WalletUtils.getAmountFromInvoice(paymentRequest).amount())) { + if (paymentRequest.amount().isDefined() && !NodeSupervisor.hasNormalChannelsWithBalance(WalletUtils.getAmountFromInvoice(paymentRequest).toLong())) { canNotHandlePayment(getString(R.string.payment_error_ln_insufficient_funds)); return false; } @@ -148,7 +147,7 @@ private boolean checkPaymentRequestValid(final PaymentRequest paymentRequest) { */ private boolean checkWalletReady() { // check that wallet is not desync, or very late compared to chain - final boolean isBlockHeightCorrect = Globals.blockCount().get() > Constants.MIN_BLOCK_HEIGHT; + final boolean isBlockHeightCorrect = app.appKit.eclairKit.nodeParams().currentBlockHeight() > Constants.MIN_BLOCK_HEIGHT; // if this is a LN payment, send button is enabled only if there is at least 1 channel capable of processing the payment. if (app == null || app.getElectrumState() == null) return false; final boolean isWalletReady = app.getElectrumState().isConnected && isBlockHeightCorrect && (!isLightningInvoice() || NodeSupervisor.hasOneNormalChannel()); @@ -160,10 +159,10 @@ private boolean checkWalletReady() { private void setupOnchainPaymentForm(final BitcoinURI bitcoinURI) { checkWalletReady(); if (bitcoinURI.amount != null) { - final MilliSatoshi amountMsat = package$.MODULE$.satoshi2millisatoshi(bitcoinURI.amount); + final MilliSatoshi amountMsat = MilliSatoshi.toMilliSatoshi(bitcoinURI.amount); mBinding.amountEditableBtcHint.setVisibility(View.GONE); mBinding.amountEditableBtcValue.setText(CoinUtils.rawAmountInUnit(amountMsat, preferredBitcoinUnit).bigDecimal().toPlainString()); - mBinding.amountEditableFiatValue.setText(WalletUtils.formatMsatToFiat(amountMsat.amount(), preferredFiatCurrency)); + mBinding.amountEditableFiatValue.setText(WalletUtils.formatMsatToFiat(amountMsat.toLong(), preferredFiatCurrency)); } else { // only open the keyboard forcibly if no amount was set in the URI. This makes for a cleaner initial display. forceFocusAmount(null); @@ -184,7 +183,7 @@ private void setupLightningPaymentForm(final PaymentRequest paymentRequest) { if (paymentRequest.amount().isDefined()) { final MilliSatoshi amountMsat = WalletUtils.getAmountFromInvoice(paymentRequest); mBinding.amountEditableBtcValue.setText(CoinUtils.rawAmountInUnit(amountMsat, preferredBitcoinUnit).bigDecimal().toPlainString()); - mBinding.amountEditableFiatValue.setText(WalletUtils.formatMsatToFiat(amountMsat.amount(), preferredFiatCurrency)); + mBinding.amountEditableFiatValue.setText(WalletUtils.formatMsatToFiat(amountMsat.toLong(), preferredFiatCurrency)); } mBinding.recipientValue.setText(paymentRequest.nodeId().toString()); final Either desc = paymentRequest.description(); @@ -269,17 +268,17 @@ public void forceFocusFees(final View view) { public void pickFees(final View view) { if (feeRatingState == Constants.FEE_RATING_SLOW) { feeRatingState = Constants.FEE_RATING_MEDIUM; - mBinding.feesValue.setText(String.valueOf(App.estimateMediumFees())); + mBinding.feesValue.setText(String.valueOf(app.estimateMediumFees())); mBinding.setFeeRatingState(feeRatingState); mBinding.feesRating.setText(R.string.payment_fees_medium); } else if (feeRatingState == Constants.FEE_RATING_MEDIUM) { feeRatingState = Constants.FEE_RATING_FAST; - mBinding.feesValue.setText(String.valueOf(App.estimateFastFees())); + mBinding.feesValue.setText(String.valueOf(app.estimateFastFees())); mBinding.setFeeRatingState(feeRatingState); mBinding.feesRating.setText(R.string.payment_fees_fast); } else if (feeRatingState == Constants.FEE_RATING_FAST) { feeRatingState = Constants.FEE_RATING_SLOW; - mBinding.feesValue.setText(String.valueOf(App.estimateSlowFees())); + mBinding.feesValue.setText(String.valueOf(app.estimateSlowFees())); mBinding.setFeeRatingState(feeRatingState); mBinding.feesRating.setText(R.string.payment_fees_slow); } else { @@ -289,7 +288,7 @@ public void pickFees(final View view) { private void setFeesToDefault() { feeRatingState = Constants.FEE_RATING_FAST; - mBinding.feesValue.setText(String.valueOf(App.estimateFastFees())); + mBinding.feesValue.setText(String.valueOf(app.estimateFastFees())); mBinding.setFeeRatingState(feeRatingState); mBinding.feesRating.setText(R.string.payment_fees_fast); } @@ -316,7 +315,7 @@ public void confirmPayment(final View view) { try { if (isLightningInvoice()) { final PaymentRequest paymentRequest = invoice.right().get(); - final long amountMsat = CoinUtils.convertStringAmountToMsat(mBinding.amountEditableBtcValue.getText().toString(), preferredBitcoinUnit.code()).amount(); + final long amountMsat = CoinUtils.convertStringAmountToMsat(mBinding.amountEditableBtcValue.getText().toString(), preferredBitcoinUnit.code()).toLong(); if (amountMsat <= 0) { handlePaymentError(R.string.payment_error_amount_zero_or_less); return; @@ -352,7 +351,7 @@ public void onPinCancel(PinDialog dialog) { if (amountSat.$greater(app.getOnchainBalance())) { handlePaymentError(R.string.payment_error_amount_onchain_insufficient_funds); return; - } else if (amountSat.amount() <= 0) { + } else if (amountSat.toLong() <= 0) { handlePaymentError(R.string.payment_error_amount_zero_or_less); return; } @@ -559,7 +558,7 @@ private void switchAmountInputUnit() { private void checkOnchainBalance(final MilliSatoshi amountMsat) { if (invoice != null && invoice.isLeft()) { - if (package$.MODULE$.millisatoshi2satoshi(amountMsat).$greater(app.getOnchainBalance())) { + if (amountMsat.truncateToSatoshi().$greater(app.getOnchainBalance())) { handlePaymentError(R.string.payment_error_amount_onchain_insufficient_funds); } else { mBinding.paymentError.setVisibility(View.GONE); @@ -572,7 +571,7 @@ private void refreshAmounts() { try { final String btcAmountString = mBinding.amountEditableBtcValue.getText().toString(); final MilliSatoshi amountMsat = CoinUtils.convertStringAmountToMsat(btcAmountString, preferredBitcoinUnit.code()); - mBinding.amountEditableFiatValue.setText(WalletUtils.convertMsatToFiat(amountMsat.amount(), preferredFiatCurrency).bigDecimal().setScale(4, RoundingMode.CEILING).toPlainString()); + mBinding.amountEditableFiatValue.setText(WalletUtils.convertMsatToFiat(amountMsat.toLong(), preferredFiatCurrency).bigDecimal().setScale(4, RoundingMode.CEILING).toPlainString()); mBinding.amountEditableBtcHint.setVisibility(Strings.isNullOrEmpty(btcAmountString) ? View.VISIBLE : View.GONE); checkOnchainBalance(amountMsat); } catch (Exception e) { @@ -638,15 +637,15 @@ public void onTextChanged(CharSequence s, int start, int before, int count) { public void onTextChanged(final CharSequence s, final int start, final int before, final int count) { try { final long feesSatPerByte = Long.parseLong(s.toString()); - if (feesSatPerByte != App.estimateSlowFees() && feesSatPerByte != App.estimateMediumFees() && feesSatPerByte != App.estimateFastFees()) { + if (feesSatPerByte != app.estimateSlowFees() && feesSatPerByte != app.estimateMediumFees() && feesSatPerByte != app.estimateFastFees()) { feeRatingState = Constants.FEE_RATING_CUSTOM; mBinding.setFeeRatingState(feeRatingState); mBinding.feesRating.setText(R.string.payment_fees_custom); } - if (feesSatPerByte <= App.estimateSlowFees() / 2) { + if (feesSatPerByte <= app.estimateSlowFees() / 2) { mBinding.feesWarning.setText(R.string.payment_fees_verylow); mBinding.feesWarning.setVisibility(View.VISIBLE); - } else if (feesSatPerByte >= App.estimateFastFees() * 2) { + } else if (feesSatPerByte >= app.estimateFastFees() * 2) { mBinding.feesWarning.setText(R.string.payment_fees_veryhigh); mBinding.feesWarning.setVisibility(View.VISIBLE); } else { diff --git a/app/src/main/java/fr/acinq/eclair/wallet/activities/StartupActivity.java b/app/src/main/java/fr/acinq/eclair/wallet/activities/StartupActivity.java index dc1d5104..007e8826 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/activities/StartupActivity.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/activities/StartupActivity.java @@ -540,7 +540,6 @@ protected Integer doInBackground(Object... params) { app.system.eventStream().subscribe(nodeSupervisor, ChannelEvent.class); app.system.eventStream().subscribe(nodeSupervisor, SyncProgress.class); app.system.eventStream().subscribe(nodeSupervisor, PaymentEvent.class); - app.system.eventStream().subscribe(nodeSupervisor, PaymentLifecycle.PaymentResult.class); // electrum payment supervisor actor app.system.actorOf(Props.create(ElectrumSupervisor.class, app.getDBHelper(), paymentsRefreshScheduler, balanceRefreshScheduler), "ElectrumSupervisor"); diff --git a/app/src/main/java/fr/acinq/eclair/wallet/actors/ElectrumSupervisor.java b/app/src/main/java/fr/acinq/eclair/wallet/actors/ElectrumSupervisor.java index 92258457..b1a854c2 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/actors/ElectrumSupervisor.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/actors/ElectrumSupervisor.java @@ -30,6 +30,7 @@ import fr.acinq.bitcoin.Satoshi; import fr.acinq.bitcoin.Transaction; import fr.acinq.bitcoin.package$; +import fr.acinq.eclair.MilliSatoshi$; import fr.acinq.eclair.blockchain.electrum.ElectrumClient; import fr.acinq.eclair.blockchain.electrum.ElectrumWallet; import fr.acinq.eclair.wallet.DBHelper; @@ -86,10 +87,10 @@ public void onReceive(final Object message) { paymentReceived.setDirection(direction); paymentReceived.setReference(walletTransactionReceive.tx().txid().toString()); if (direction == PaymentDirection.SENT) { // fee makes sense only if the tx is sent by us - paymentReceived.setFeesPaidMsat(package$.MODULE$.satoshi2millisatoshi(fee).amount()); + paymentReceived.setFeesPaidMsat(MilliSatoshi$.MODULE$.toMilliSatoshi(fee).toLong()); } paymentReceived.setTxPayload(Hex.toHexString(bos.toByteArray())); - paymentReceived.setAmountPaidMsat(package$.MODULE$.satoshi2millisatoshi(amount).amount()); + paymentReceived.setAmountPaidMsat(MilliSatoshi$.MODULE$.toMilliSatoshi(amount).toLong()); paymentReceived.setConfidenceBlocks((int) walletTransactionReceive.depth()); paymentReceived.setConfidenceType(0); diff --git a/app/src/main/java/fr/acinq/eclair/wallet/actors/NodeSupervisor.java b/app/src/main/java/fr/acinq/eclair/wallet/actors/NodeSupervisor.java index c21b0ce5..eddce9d6 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/actors/NodeSupervisor.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/actors/NodeSupervisor.java @@ -21,13 +21,20 @@ import akka.actor.UntypedActor; import com.google.common.base.Strings; import fr.acinq.bitcoin.*; +import fr.acinq.eclair.CltvExpiryDelta; +import fr.acinq.eclair.MilliSatoshi; import fr.acinq.bitcoin.package$; +import fr.acinq.eclair.MilliSatoshi$; import fr.acinq.eclair.ShortChannelId; import fr.acinq.eclair.channel.*; import fr.acinq.eclair.db.BackupCompleted$; +import fr.acinq.eclair.payment.PaymentFailed; +import fr.acinq.eclair.payment.PaymentFailure; +import fr.acinq.eclair.payment.PaymentFailure$; import fr.acinq.eclair.payment.PaymentLifecycle; import fr.acinq.eclair.payment.PaymentReceived; import fr.acinq.eclair.payment.PaymentRequest; +import fr.acinq.eclair.payment.PaymentSent; import fr.acinq.eclair.router.NORMAL$; import fr.acinq.eclair.router.SyncProgress; import fr.acinq.eclair.transactions.DirectedHtlc; @@ -112,9 +119,9 @@ private static scala.collection.immutable.List getExtra final PaymentRequest.ExtraHop hop = new PaymentRequest.ExtraHop( Crypto.PublicKey$.MODULE$.apply(ByteVector.view(Hex.decode(channel.getPeerNodeId())), false), ShortChannelId.apply(channel.getShortChannelId()), - channel.feeBaseMsat, + new MilliSatoshi(channel.feeBaseMsat), channel.feeProportionalMillionths, - channel.cltvExpiryDelta); + new CltvExpiryDelta(channel.cltvExpiryDelta)); hops.add(hop); return JavaConverters.asScalaIteratorConverter(hops.iterator()).asScala().toList(); } @@ -155,7 +162,7 @@ public void onReceive(final Object message) { } } c.htlcsInFlightCount = htlcsCount; - c.sendableBalanceMsat = event.currentData().commitments().availableBalanceForSendMsat(); + c.sendableBalanceMsat = event.currentData().commitments().availableBalanceForSend().toLong(); // restore data from DB that were sent only once by the node and may have be persisted final LocalChannel channelInDB = dbHelper.getLocalChannel(c.getChannelId()); @@ -214,12 +221,12 @@ else if (message instanceof ChannelSignatureReceived) { final LocalChannel c = activeChannelsMap.get(event.channel()); if (c != null) { final LocalCommit localCommit = event.commitments().localCommit(); - c.setChannelReserveSat(event.commitments().localParams().channelReserveSatoshis()); - c.setMinimumHtlcAmountMsat(event.commitments().localParams().htlcMinimumMsat()); + c.setChannelReserveSat(event.commitments().localParams().channelReserve().toLong()); + c.setMinimumHtlcAmountMsat(event.commitments().localParams().htlcMinimum().toLong()); c.htlcsInFlightCount = localCommit.spec().htlcs().iterator().size(); - c.sendableBalanceMsat = event.commitments().availableBalanceForSendMsat(); - c.setBalanceMsat(localCommit.spec().toLocalMsat()); - c.setCapacityMsat(localCommit.spec().totalFunds()); + c.sendableBalanceMsat = event.commitments().availableBalanceForSend().toLong(); + c.setBalanceMsat(localCommit.spec().toLocal().toLong()); + c.setCapacityMsat(localCommit.spec().totalFunds().toLong()); balanceRefreshScheduler.tell(Constants.REFRESH, null); channelsRefreshScheduler.tell(Constants.REFRESH, null); } @@ -245,8 +252,8 @@ else if (message instanceof Terminated) { channelsRefreshScheduler.tell(Constants.REFRESH, null); } // ---- channel is in error - else if (message instanceof ChannelErrorOccured) { - final ChannelErrorOccured event = (ChannelErrorOccured) message; + else if (message instanceof ChannelErrorOccurred) { + final ChannelErrorOccurred event = (ChannelErrorOccurred) message; final LocalChannel c = activeChannelsMap.get(event.channel()); if (c != null) { if (event.error() instanceof Channel.LocalError) { @@ -308,7 +315,7 @@ else if (message instanceof ChannelStateChanged) { // Same thing for CLOSING -> CLOSED if (!CLOSED$.MODULE$.toString().equals(event.currentState().toString()) && !WAIT_FOR_INIT_INTERNAL$.MODULE$.toString().equals(event.previousState().toString())) { - final MilliSatoshi balanceLeft = new MilliSatoshi(d.commitments().localCommit().spec().toLocalMsat()); + final MilliSatoshi balanceLeft = new MilliSatoshi(d.commitments().localCommit().spec().toLocal().toLong()); EventBus.getDefault().post(new ClosingChannelNotificationEvent( c.getChannelId(), c.getPeerNodeId(), ClosingType.LOCAL.equals(c.getClosingType()), balanceLeft, c.getToSelfDelayBlocks())); } @@ -317,15 +324,15 @@ else if (message instanceof ChannelStateChanged) { if (event.currentData() instanceof HasCommitments) { final Commitments commitments = ((HasCommitments) event.currentData()).commitments(); c.setLocalFeatures(commitments.remoteParams().localFeatures().toHex()); - c.setToSelfDelayBlocks(commitments.remoteParams().toSelfDelay()); - c.remoteToSelfDelayBlocks = commitments.localParams().toSelfDelay(); + c.setToSelfDelayBlocks(commitments.remoteParams().toSelfDelay().toInt()); + c.remoteToSelfDelayBlocks = commitments.localParams().toSelfDelay().toInt(); c.htlcsInFlightCount = commitments.localCommit().spec().htlcs().iterator().size(); - c.setChannelReserveSat(commitments.localParams().channelReserveSatoshis()); - c.setMinimumHtlcAmountMsat(commitments.localParams().htlcMinimumMsat()); + c.setChannelReserveSat(commitments.localParams().channelReserve().toLong()); + c.setMinimumHtlcAmountMsat(commitments.localParams().htlcMinimum().toLong()); c.setFundingTxId(commitments.commitInput().outPoint().txid().toString()); - c.sendableBalanceMsat = commitments.availableBalanceForSendMsat(); - c.setBalanceMsat(commitments.localCommit().spec().toLocalMsat()); - c.setCapacityMsat(commitments.localCommit().spec().totalFunds()); + c.sendableBalanceMsat = commitments.availableBalanceForSend().toLong(); + c.setBalanceMsat(commitments.localCommit().spec().toLocal().toLong()); + c.setCapacityMsat(commitments.localCommit().spec().totalFunds().toLong()); } activeChannelsMap.put(event.channel(), c); @@ -339,20 +346,20 @@ else if (message instanceof LocalChannelUpdate) { final LocalChannelUpdate event = (LocalChannelUpdate) message; final LocalChannel c = activeChannelsMap.get(event.channel()); if (event.channelUpdate() != null && c != null) { - c.feeBaseMsat = event.channelUpdate().feeBaseMsat(); + c.feeBaseMsat = event.channelUpdate().feeBaseMsat().toLong(); c.feeProportionalMillionths = event.channelUpdate().feeProportionalMillionths(); - c.cltvExpiryDelta = event.channelUpdate().cltvExpiryDelta(); + c.cltvExpiryDelta = event.channelUpdate().cltvExpiryDelta().toInt(); } } // ---- failed outbound payment - else if (message instanceof PaymentLifecycle.PaymentFailed) { - final PaymentLifecycle.PaymentFailed event = (PaymentLifecycle.PaymentFailed) message; + else if (message instanceof PaymentFailed) { + final PaymentFailed event = (PaymentFailed) message; final Payment paymentInDB = dbHelper.getPayment(event.paymentHash().toString(), PaymentType.BTC_LN); if (paymentInDB != null) { dbHelper.updatePaymentFailed(paymentInDB); // extract failure cause to generate a pretty error message final ArrayList errorList = new ArrayList<>(); - final Seq failures = PaymentLifecycle.transformForUser(event.failures()); + final Seq failures = PaymentFailure$.MODULE$.transformForUser(event.failures()); if (failures.size() > 0) { for (int i = 0; i < failures.size(); i++) { errorList.add(LightningPaymentError.generateDetailedErrorCause(failures.apply(i))); @@ -365,11 +372,11 @@ else if (message instanceof PaymentLifecycle.PaymentFailed) { } } // ---- successful outbound payment - else if (message instanceof PaymentLifecycle.PaymentSucceeded) { - final PaymentLifecycle.PaymentSucceeded event = (PaymentLifecycle.PaymentSucceeded) message; + else if (message instanceof PaymentSent) { + final PaymentSent event = (PaymentSent) message; final Payment paymentInDB = dbHelper.getPayment(event.paymentHash().toString(), PaymentType.BTC_LN); if (paymentInDB != null) { - dbHelper.updatePaymentPaid(paymentInDB, event.amountMsat(), event.amountMsat() - paymentInDB.getAmountSentMsat(), event.paymentPreimage().toString()); + dbHelper.updatePaymentPaid(paymentInDB, event.amount().toLong(), event.amount().toLong() - paymentInDB.getAmountSentMsat(), event.paymentPreimage().toString()); EventBus.getDefault().post(new LNPaymentSuccessEvent(paymentInDB)); paymentRefreshScheduler.tell(Constants.REFRESH, null); } else { @@ -383,13 +390,13 @@ else if (message instanceof fr.acinq.eclair.payment.PaymentReceived) { final Payment paymentInDB = dbHelper.getPayment(paymentHash, PaymentType.BTC_LN); log.debug("received a successful payment with hash={}", paymentHash); if (paymentInDB != null) { - dbHelper.updatePaymentReceived(paymentInDB, pr.amount().amount()); + dbHelper.updatePaymentReceived(paymentInDB, pr.amount().toLong()); } else { final Payment p = new Payment(); p.setType(PaymentType.BTC_LN); p.setDirection(PaymentDirection.RECEIVED); p.setReference(paymentHash); - p.setAmountPaidMsat(pr.amount().amount()); + p.setAmountPaidMsat(pr.amount().toLong()); p.setStatus(PaymentStatus.PAID); p.setUpdated(new Date()); dbHelper.insertOrUpdatePayment(p); @@ -406,7 +413,7 @@ else if (message instanceof fr.acinq.eclair.payment.PaymentReceived) { public static boolean hasNormalChannelsWithBalance(final long requiredBalanceMsat) { for (LocalChannel d : activeChannelsMap.values()) { if ((NORMAL$.MODULE$.toString().equals(d.state) || OFFLINE$.MODULE$.toString().equals(d.state)) - & d.getBalanceMsat() > requiredBalanceMsat + package$.MODULE$.satoshi2millisatoshi(new Satoshi(d.getChannelReserveSat())).amount()) { + & d.getBalanceMsat() > requiredBalanceMsat + MilliSatoshi$.MODULE$.toMilliSatoshi(new Satoshi(d.getChannelReserveSat())).toLong()) { return true; } } diff --git a/app/src/main/java/fr/acinq/eclair/wallet/adapters/LightningErrorHolder.java b/app/src/main/java/fr/acinq/eclair/wallet/adapters/LightningErrorHolder.java index a5a9a697..585244b7 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/adapters/LightningErrorHolder.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/adapters/LightningErrorHolder.java @@ -22,6 +22,7 @@ import android.view.View; import android.widget.TextView; +import fr.acinq.eclair.payment.LocalFailure; import fr.acinq.eclair.payment.PaymentLifecycle; import fr.acinq.eclair.wallet.R; import fr.acinq.eclair.wallet.models.LightningPaymentError; @@ -64,7 +65,7 @@ void bindErrorItem(final LightningPaymentError error, final int counter, final i mErrorOriginLabel.setVisibility(View.VISIBLE); mErrorOrigin.setVisibility(View.VISIBLE); mErrorOrigin.setText(error.getOrigin()); - } else if (error.getType().equals(PaymentLifecycle.LocalFailure.class.getSimpleName())) { + } else if (error.getType().equals(LocalFailure.class.getSimpleName())) { mErrorOriginLabel.setVisibility(View.VISIBLE); mErrorOrigin.setVisibility(View.VISIBLE); mErrorOrigin.setText("Your node"); diff --git a/app/src/main/java/fr/acinq/eclair/wallet/adapters/LocalChannelItemHolder.java b/app/src/main/java/fr/acinq/eclair/wallet/adapters/LocalChannelItemHolder.java index 9b753fe5..d2bc647d 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/adapters/LocalChannelItemHolder.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/adapters/LocalChannelItemHolder.java @@ -25,14 +25,14 @@ import android.widget.ProgressBar; import android.widget.TextView; -import fr.acinq.bitcoin.MilliSatoshi; +import fr.acinq.eclair.MilliSatoshi; import fr.acinq.eclair.CoinUnit; import fr.acinq.eclair.CoinUtils; -import fr.acinq.eclair.Globals; import fr.acinq.eclair.channel.CLOSED$; import fr.acinq.eclair.channel.CLOSING$; import fr.acinq.eclair.channel.NORMAL$; import fr.acinq.eclair.channel.OFFLINE$; +import fr.acinq.eclair.wallet.App; import fr.acinq.eclair.wallet.BuildConfig; import fr.acinq.eclair.wallet.R; import fr.acinq.eclair.wallet.activities.ChannelDetailsActivity; @@ -109,11 +109,13 @@ protected void bindItem(final LocalChannel item, final String fiatCode, final Co state.setTextColor(ContextCompat.getColor(itemView.getContext(), R.color.orange)); } + + Long currentBlockHeight = 123L; //appKit.eclairKit.nodeParams().currentBlockHeight(); // ---- additional dynamic info, such as delayed closing tx, inflight htlcs... if (CLOSING$.MODULE$.toString().equals(item.state) && ClosingType.LOCAL.equals(item.getClosingType())) { // TODO: get the exact block at which the closing tx will be broadcast - if (Globals.blockCount().get() > 0) { - final long remainingBlocks = item.getRefundAtBlock() - Globals.blockCount().get(); + if (currentBlockHeight > 0) { + final long remainingBlocks = item.getRefundAtBlock() - currentBlockHeight; if (remainingBlocks > 0) { delayedClosing.setText(itemView.getResources().getString(R.string.channelitem_delayed_closing, remainingBlocks, remainingBlocks > 1 ? "s" : "")); } else { diff --git a/app/src/main/java/fr/acinq/eclair/wallet/adapters/PaymentItemHolder.java b/app/src/main/java/fr/acinq/eclair/wallet/adapters/PaymentItemHolder.java index c0381a6e..1d3b4d6e 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/adapters/PaymentItemHolder.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/adapters/PaymentItemHolder.java @@ -27,7 +27,7 @@ import android.widget.ImageView; import android.widget.TextView; import com.google.common.base.Strings; -import fr.acinq.bitcoin.MilliSatoshi; +import fr.acinq.eclair.MilliSatoshi; import fr.acinq.bitcoin.package$; import fr.acinq.eclair.CoinUnit; import fr.acinq.eclair.CoinUtils; @@ -106,7 +106,7 @@ public void bindPaymentItem(final int position, final Payment payment, final Str } else { WalletUtils.printAmountInView(mAmountValue, CoinUtils.formatAmountInUnit(new MilliSatoshi(amountMsat), prefUnit, false), amountPrefix); mAmountUnit.setText(prefUnit.shortLabel()); - mFees.setText(NumberFormat.getInstance().format(package$.MODULE$.millisatoshi2satoshi(new MilliSatoshi(payment.getFeesPaidMsat())).amount())); + mFees.setText(NumberFormat.getInstance().format((new MilliSatoshi(payment.getFeesPaidMsat())).truncateToSatoshi().toLong())); mFeesUnit.setText(Constants.SATOSHI_CODE); } diff --git a/app/src/main/java/fr/acinq/eclair/wallet/customviews/CoinAmountView.java b/app/src/main/java/fr/acinq/eclair/wallet/customviews/CoinAmountView.java index 3030ad20..36faee82 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/customviews/CoinAmountView.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/customviews/CoinAmountView.java @@ -28,7 +28,7 @@ import android.view.LayoutInflater; import android.view.View; import android.widget.TextView; -import fr.acinq.bitcoin.MilliSatoshi; +import fr.acinq.eclair.MilliSatoshi; import fr.acinq.eclair.CoinUnit; import fr.acinq.eclair.CoinUtils; import fr.acinq.eclair.wallet.R; @@ -65,7 +65,7 @@ public void refreshUnits() { this.prefBtcUnit = WalletUtils.getPreferredCoinUnit(prefs); this.prefFiatCurrency = WalletUtils.getPreferredFiat(prefs); if (WalletUtils.shouldDisplayInFiat(prefs) && !forceBtcUnit) { - WalletUtils.printAmountInView(amountTextView, WalletUtils.formatMsatToFiat(amountMsat.amount(), prefFiatCurrency)); + WalletUtils.printAmountInView(amountTextView, WalletUtils.formatMsatToFiat(amountMsat.toLong(), prefFiatCurrency)); unitTextView.setText(prefFiatCurrency.toUpperCase()); } else { WalletUtils.printAmountInView(amountTextView, CoinUtils.formatAmountInUnit(amountMsat, prefBtcUnit, false)); diff --git a/app/src/main/java/fr/acinq/eclair/wallet/events/ClosingChannelNotificationEvent.java b/app/src/main/java/fr/acinq/eclair/wallet/events/ClosingChannelNotificationEvent.java index 50dfae05..271fda8b 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/events/ClosingChannelNotificationEvent.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/events/ClosingChannelNotificationEvent.java @@ -16,7 +16,7 @@ package fr.acinq.eclair.wallet.events; -import fr.acinq.bitcoin.MilliSatoshi; +import fr.acinq.eclair.MilliSatoshi; public class ClosingChannelNotificationEvent { diff --git a/app/src/main/java/fr/acinq/eclair/wallet/events/ReceivedLNPaymentNotificationEvent.java b/app/src/main/java/fr/acinq/eclair/wallet/events/ReceivedLNPaymentNotificationEvent.java index fcbfe1f1..7ccfe9ee 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/events/ReceivedLNPaymentNotificationEvent.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/events/ReceivedLNPaymentNotificationEvent.java @@ -16,7 +16,7 @@ package fr.acinq.eclair.wallet.events; -import fr.acinq.bitcoin.MilliSatoshi; +import fr.acinq.eclair.MilliSatoshi; public class ReceivedLNPaymentNotificationEvent { diff --git a/app/src/main/java/fr/acinq/eclair/wallet/fragments/ChannelsListFragment.java b/app/src/main/java/fr/acinq/eclair/wallet/fragments/ChannelsListFragment.java index c0c60fc0..3549a1f9 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/fragments/ChannelsListFragment.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/fragments/ChannelsListFragment.java @@ -26,7 +26,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import fr.acinq.bitcoin.MilliSatoshi; +import fr.acinq.eclair.MilliSatoshi; import fr.acinq.eclair.wallet.App; import fr.acinq.eclair.wallet.DBHelper; import fr.acinq.eclair.wallet.R; diff --git a/app/src/main/java/fr/acinq/eclair/wallet/fragments/PaymentRequestParametersDialog.java b/app/src/main/java/fr/acinq/eclair/wallet/fragments/PaymentRequestParametersDialog.java index 3d6090db..a5c7a065 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/fragments/PaymentRequestParametersDialog.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/fragments/PaymentRequestParametersDialog.java @@ -30,7 +30,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import fr.acinq.bitcoin.MilliSatoshi; +import fr.acinq.eclair.MilliSatoshi; import fr.acinq.bitcoin.package$; import fr.acinq.eclair.CoinUnit; import fr.acinq.eclair.CoinUtils; @@ -92,10 +92,10 @@ private MilliSatoshi extractAmount(final String amountString) { if (Strings.isNullOrEmpty(amountString)) { mBinding.amountFiat.setText(""); } else { - final MilliSatoshi amount = new MilliSatoshi(CoinUtils.convertStringAmountToMsat(amountString, prefUnit.code()).amount()); - package$.MODULE$.millisatoshi2btc(amount); - mBinding.amountFiat.setText(getContext().getString(R.string.amount_to_fiat, WalletUtils.formatMsatToFiatWithUnit(amount.amount(), fiatUnit))); - if (amount.amount() > maxReceivableAmount.amount()) { + final MilliSatoshi amount = new MilliSatoshi(CoinUtils.convertStringAmountToMsat(amountString, prefUnit.code()).toLong()); + package$.MODULE$.satoshi2btc(amount.truncateToSatoshi()); + mBinding.amountFiat.setText(getContext().getString(R.string.amount_to_fiat, WalletUtils.formatMsatToFiatWithUnit(amount.toLong(), fiatUnit))); + if (amount.toLong() > maxReceivableAmount.toLong()) { mBinding.setAmountWarning(getContext().getString(R.string.dialog_prparams_amount_error_excessive, CoinUtils.formatAmountInUnit(maxReceivableAmount, prefUnit, true))); } else { mBinding.setAmountError(null); diff --git a/app/src/main/java/fr/acinq/eclair/wallet/fragments/ReceivePaymentFragment.java b/app/src/main/java/fr/acinq/eclair/wallet/fragments/ReceivePaymentFragment.java index 234acccf..5d97e31b 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/fragments/ReceivePaymentFragment.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/fragments/ReceivePaymentFragment.java @@ -33,7 +33,7 @@ import android.view.ViewGroup; import android.widget.Toast; import com.google.common.base.Strings; -import fr.acinq.bitcoin.MilliSatoshi; +import fr.acinq.eclair.MilliSatoshi; import fr.acinq.eclair.CoinUtils; import fr.acinq.eclair.blockchain.electrum.ElectrumWallet; import fr.acinq.eclair.payment.PaymentRequest; @@ -346,7 +346,7 @@ private void updateLightningAmountView() { mBinding.lightningAmountLabel.setVisibility(View.VISIBLE); mBinding.lightningAmount.setText(Html.fromHtml(getString(R.string.receivepayment_lightning_amount_value, CoinUtils.formatAmountInUnit(this.lightningAmount.get(), WalletUtils.getPreferredCoinUnit(prefs), true), - WalletUtils.formatMsatToFiatWithUnit(this.lightningAmount.get().amount(), WalletUtils.getPreferredFiat(prefs))))); + WalletUtils.formatMsatToFiatWithUnit(this.lightningAmount.get().toLong(), WalletUtils.getPreferredFiat(prefs))))); } } diff --git a/app/src/main/java/fr/acinq/eclair/wallet/fragments/openchannel/OpenChannelCapacityFragment.java b/app/src/main/java/fr/acinq/eclair/wallet/fragments/openchannel/OpenChannelCapacityFragment.java index 6f191923..c79d1d8c 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/fragments/openchannel/OpenChannelCapacityFragment.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/fragments/openchannel/OpenChannelCapacityFragment.java @@ -66,7 +66,7 @@ public interface OnCapacityConfirmListener { } final Satoshi minFunding = new Satoshi(100000); // 1 mBTC - final Satoshi maxFunding = new Satoshi(Channel.MAX_FUNDING_SATOSHIS()); + final Satoshi maxFunding = Channel.MAX_FUNDING(); private int feeRatingState = Constants.FEE_RATING_FAST; private String preferredFiatCurrency = Constants.FIAT_USD; private CoinUnit preferredBitcoinUnit = CoinUtils.getUnitFromString(Constants.BTC_CODE); @@ -135,14 +135,14 @@ private Long extractFundingFees(final String feesString) { mBinding.useAllFundsCheckbox.setChecked(false); try { final long feesSatPerByte = Long.parseLong(feesString); - if (feesSatPerByte != App.estimateSlowFees() && feesSatPerByte != App.estimateMediumFees() && feesSatPerByte != App.estimateFastFees()) { + if (feesSatPerByte != getApp().estimateSlowFees() && feesSatPerByte != getApp().estimateMediumFees() && feesSatPerByte != getApp().estimateFastFees()) { feeRatingState = Constants.FEE_RATING_CUSTOM; mBinding.setFeeRatingState(feeRatingState); mBinding.fundingFeesRating.setText(R.string.payment_fees_custom); } - if (feesSatPerByte <= App.estimateSlowFees() / 2) { + if (feesSatPerByte <= getApp().estimateSlowFees() / 2) { mBinding.setFeesWarning(getString(R.string.payment_fees_verylow)); - } else if (feesSatPerByte >= App.estimateFastFees() * 2) { + } else if (feesSatPerByte >= getApp().estimateFastFees() * 2) { mBinding.setFeesWarning(getString(R.string.payment_fees_veryhigh)); } else { mBinding.setFeesWarning(null); @@ -176,11 +176,11 @@ private Satoshi extractCapacity(final String amount) { try { final Satoshi capacity = CoinUtils.convertStringAmountToSat(amount, preferredBitcoinUnit.code()); mBinding.capacityFiat.setText(getString(R.string.amount_to_fiat, WalletUtils.formatSatToFiatWithUnit(capacity, preferredFiatCurrency))); - if (capacity.amount() < minFunding.amount() || capacity.amount() > maxFunding.amount()) { + if (capacity.$less(minFunding) || capacity.$greater(maxFunding)) { mBinding.setAmountError(getString(R.string.openchannel_capacity_invalid, CoinUtils.formatAmountInUnit(minFunding, preferredBitcoinUnit, false), CoinUtils.formatAmountInUnit(maxFunding, preferredBitcoinUnit, true))); return null; - } else if (getApp() != null && capacity.amount() > getApp().getOnchainBalance().amount()) { + } else if (getApp() != null && capacity.$greater(getApp().getOnchainBalance())) { mBinding.setAmountError(getString(R.string.openchannel_capacity_notenoughfunds)); return null; } else { @@ -213,7 +213,7 @@ public void run() { try { if (getApp() != null) { final Long feesPerKw = fr.acinq.eclair.package$.MODULE$.feerateByte2Kw(Long.parseLong(mBinding.fundingFeesValue.getText().toString())); - final long capacitySat = Math.min(getApp().getAvailableFundsAfterFees(feesPerKw).amount(), Channel.MAX_FUNDING_SATOSHIS()); + final long capacitySat = Math.min(getApp().getAvailableFundsAfterFees(feesPerKw).toLong(), Channel.MAX_FUNDING().toLong()); runOnUiThread(() -> { mBinding.capacityValue.setText(CoinUtils.rawAmountInUnit(new Satoshi(capacitySat), preferredBitcoinUnit).bigDecimal().toPlainString()); mBinding.capacityValue.setEnabled(false); @@ -244,17 +244,17 @@ private App getApp() { private void pickFees() { if (feeRatingState == Constants.FEE_RATING_SLOW) { feeRatingState = Constants.FEE_RATING_MEDIUM; - mBinding.fundingFeesValue.setText(String.valueOf(App.estimateMediumFees())); + mBinding.fundingFeesValue.setText(String.valueOf(getApp().estimateMediumFees())); mBinding.setFeeRatingState(feeRatingState); mBinding.fundingFeesRating.setText(R.string.payment_fees_medium); } else if (feeRatingState == Constants.FEE_RATING_MEDIUM) { feeRatingState = Constants.FEE_RATING_FAST; - mBinding.fundingFeesValue.setText(String.valueOf(App.estimateFastFees())); + mBinding.fundingFeesValue.setText(String.valueOf(getApp().estimateFastFees())); mBinding.setFeeRatingState(feeRatingState); mBinding.fundingFeesRating.setText(R.string.payment_fees_fast); } else if (feeRatingState == Constants.FEE_RATING_FAST) { feeRatingState = Constants.FEE_RATING_SLOW; - mBinding.fundingFeesValue.setText(String.valueOf(App.estimateSlowFees())); + mBinding.fundingFeesValue.setText(String.valueOf(getApp().estimateSlowFees())); mBinding.setFeeRatingState(feeRatingState); mBinding.fundingFeesRating.setText(R.string.payment_fees_slow); } else { @@ -264,7 +264,7 @@ private void pickFees() { private void setFeesToDefault() { feeRatingState = Constants.FEE_RATING_FAST; - mBinding.fundingFeesValue.setText(String.valueOf(App.estimateFastFees())); + mBinding.fundingFeesValue.setText(String.valueOf(getApp().estimateFastFees())); mBinding.setFeeRatingState(feeRatingState); mBinding.fundingFeesRating.setText(R.string.payment_fees_fast); } diff --git a/app/src/main/java/fr/acinq/eclair/wallet/fragments/openchannel/OpenChannelLiquidityFragment.java b/app/src/main/java/fr/acinq/eclair/wallet/fragments/openchannel/OpenChannelLiquidityFragment.java index 277a636f..c69c04f4 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/fragments/openchannel/OpenChannelLiquidityFragment.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/fragments/openchannel/OpenChannelLiquidityFragment.java @@ -27,7 +27,7 @@ import android.view.View; import android.view.ViewGroup; import fr.acinq.bitcoin.MilliBtc; -import fr.acinq.bitcoin.MilliSatoshi; +import fr.acinq.eclair.MilliSatoshi; import fr.acinq.bitcoin.Satoshi; import fr.acinq.bitcoin.package$; import fr.acinq.eclair.CoinUnit; @@ -60,7 +60,7 @@ private enum LIQUIDITY_REQUESTS { LIQUIDITY_REQUESTS(final long inboundCapacity_mbtc) { this.inboundCapacity = new MilliBtc(BigDecimal.exact(inboundCapacity_mbtc)); if (App.walletContext != null) { - this.cost = package$.MODULE$.millibtc2millisatoshi(new MilliBtc(inboundCapacity.amount().$times(BigDecimal.double2bigDecimal(App.walletContext.liquidityRate)))); + this.cost = MilliSatoshi.toMilliSatoshi(new MilliBtc(inboundCapacity.toBigDecimal().$times(BigDecimal.double2bigDecimal(App.walletContext.liquidityRate)))); } else { this.cost = new MilliSatoshi(0); } @@ -103,21 +103,21 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, CoinUtils.formatAmountInUnit(LIQUIDITY_REQUESTS._10_MBTC.inboundCapacity, preferredBitcoinUnit, true))); mBinding.liquidityOpt10Cost.setText(getString(R.string.openchannel_liquidity_cost, CoinUtils.formatAmountInUnit(LIQUIDITY_REQUESTS._10_MBTC.cost, preferredBitcoinUnit, true), - WalletUtils.formatMsatToFiatWithUnit(LIQUIDITY_REQUESTS._10_MBTC.cost.amount(), fiatUnit))); + WalletUtils.formatMsatToFiatWithUnit(LIQUIDITY_REQUESTS._10_MBTC.cost.toLong(), fiatUnit))); mBinding.liquidityOpt25.setOnClickListener(v -> mBinding.setLiquidityOpt(2)); mBinding.liquidityOpt25Title.setText(getString(R.string.openchannel_liquidity_label, CoinUtils.formatAmountInUnit(LIQUIDITY_REQUESTS._25_MBTC.inboundCapacity, preferredBitcoinUnit, true))); mBinding.liquidityOpt25Cost.setText(getString(R.string.openchannel_liquidity_cost, CoinUtils.formatAmountInUnit(LIQUIDITY_REQUESTS._25_MBTC.cost, preferredBitcoinUnit, true), - WalletUtils.formatMsatToFiatWithUnit(LIQUIDITY_REQUESTS._25_MBTC.cost.amount(), fiatUnit))); + WalletUtils.formatMsatToFiatWithUnit(LIQUIDITY_REQUESTS._25_MBTC.cost.toLong(), fiatUnit))); mBinding.liquidityOpt50.setOnClickListener(v -> mBinding.setLiquidityOpt(3)); mBinding.liquidityOpt50Title.setText(getString(R.string.openchannel_liquidity_label, CoinUtils.formatAmountInUnit(LIQUIDITY_REQUESTS._50_MBTC.inboundCapacity, preferredBitcoinUnit, true))); mBinding.liquidityOpt50Cost.setText(getString(R.string.openchannel_liquidity_cost, CoinUtils.formatAmountInUnit(LIQUIDITY_REQUESTS._50_MBTC.cost, preferredBitcoinUnit, true), - WalletUtils.formatMsatToFiatWithUnit(LIQUIDITY_REQUESTS._50_MBTC.cost.amount(), fiatUnit))); + WalletUtils.formatMsatToFiatWithUnit(LIQUIDITY_REQUESTS._50_MBTC.cost.toLong(), fiatUnit))); mBinding.buttonBack.setOnClickListener(v -> { mBinding.setLiquidityOpt(0); diff --git a/app/src/main/java/fr/acinq/eclair/wallet/models/LightningPaymentError.java b/app/src/main/java/fr/acinq/eclair/wallet/models/LightningPaymentError.java index ffd44a84..cf216268 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/models/LightningPaymentError.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/models/LightningPaymentError.java @@ -19,7 +19,11 @@ import android.os.Parcel; import android.os.Parcelable; import fr.acinq.eclair.channel.ChannelException; +import fr.acinq.eclair.payment.LocalFailure; import fr.acinq.eclair.payment.PaymentLifecycle; +import fr.acinq.eclair.payment.PaymentFailure; +import fr.acinq.eclair.payment.RemoteFailure; +import fr.acinq.eclair.payment.UnreadableRemoteFailure; import fr.acinq.eclair.router.Hop; import fr.acinq.eclair.router.RouteNotFound$; import scala.collection.JavaConverters; @@ -75,16 +79,16 @@ public LightningPaymentError(Parcel in) { } /** - * Parses a {@link PaymentLifecycle.PaymentFailure} sent by eclair core and generates a {@link LightningPaymentError}. + * Parses a {@link PaymentFailure} sent by eclair core and generates a {@link LightningPaymentError}. * According to the failure type, the resulting error may contain a list of the nodes in the failed route. * The type of the error is always set, as well as the cause, be it unknown. * * @param failure failure in the payment route * @return */ - public static LightningPaymentError generateDetailedErrorCause(final PaymentLifecycle.PaymentFailure failure) { - if (failure instanceof PaymentLifecycle.RemoteFailure) { - final PaymentLifecycle.RemoteFailure rf = (PaymentLifecycle.RemoteFailure) failure; + public static LightningPaymentError generateDetailedErrorCause(final PaymentFailure failure) { + if (failure instanceof RemoteFailure) { + final RemoteFailure rf = (RemoteFailure) failure; final String type = rf.getClass().getSimpleName(); final String cause = rf.e().failureMessage().message(); final String origin = rf.e().originNode().toString(); @@ -105,8 +109,8 @@ public static LightningPaymentError generateDetailedErrorCause(final PaymentLife } return new LightningPaymentError(type, cause, origin, originChannelId, hopsNodesPK); - } else if (failure instanceof PaymentLifecycle.LocalFailure) { - final PaymentLifecycle.LocalFailure lf = (PaymentLifecycle.LocalFailure) failure; + } else if (failure instanceof LocalFailure) { + final LocalFailure lf = (LocalFailure) failure; final String type = "Local"; String cause; String originChannelId = null; @@ -121,8 +125,8 @@ public static LightningPaymentError generateDetailedErrorCause(final PaymentLife } return new LightningPaymentError(type, cause, null, originChannelId, null); - } else if (failure instanceof PaymentLifecycle.UnreadableRemoteFailure) { - final PaymentLifecycle.UnreadableRemoteFailure unreadable = (PaymentLifecycle.UnreadableRemoteFailure) failure; + } else if (failure instanceof UnreadableRemoteFailure) { + final UnreadableRemoteFailure unreadable = (UnreadableRemoteFailure) failure; final String type = unreadable.getClass().getSimpleName(); final String cause = "A peer on the route failed the payment with an non readable cause"; final List hopsNodesPK = new ArrayList<>(); diff --git a/app/src/main/java/fr/acinq/eclair/wallet/utils/WalletUtils.java b/app/src/main/java/fr/acinq/eclair/wallet/utils/WalletUtils.java index 58b512e4..5915fa00 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/utils/WalletUtils.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/utils/WalletUtils.java @@ -51,7 +51,9 @@ import com.typesafe.config.ConfigFactory; import fr.acinq.bitcoin.*; import fr.acinq.bitcoin.package$; +import fr.acinq.eclair.MilliSatoshi; import fr.acinq.eclair.CoinUnit; +import fr.acinq.eclair.MilliSatoshi$; import fr.acinq.eclair.payment.PaymentRequest; import fr.acinq.eclair.wallet.App; import fr.acinq.eclair.wallet.BuildConfig; @@ -256,7 +258,7 @@ public static String getPreferredFiat(final SharedPreferences prefs) { */ public static BigDecimal convertMsatToFiat(final long amountMsat, final String fiatCode) { final double rate = App.RATES.containsKey(fiatCode) ? App.RATES.get(fiatCode) : -1.0f; - return package$.MODULE$.millisatoshi2btc(new MilliSatoshi(amountMsat)).amount().$times(BigDecimal.decimal(rate)); + return package$.MODULE$.satoshi2btc(new MilliSatoshi(amountMsat).truncateToSatoshi()).toBigDecimal().$times(BigDecimal.decimal(rate)); } /** @@ -268,7 +270,7 @@ public static BigDecimal convertMsatToFiat(final long amountMsat, final String f */ public static MilliSatoshi convertFiatToMsat(final String fiatAmount, final String fiatCode) { final double rate = App.RATES.containsKey(fiatCode) ? App.RATES.get(fiatCode) : -1.0f; - return package$.MODULE$.btc2millisatoshi(new Btc(BigDecimal$.MODULE$.apply(fiatAmount).$div(BigDecimal.decimal(rate)))); + return MilliSatoshi$.MODULE$.toMilliSatoshi(package$.MODULE$.btc2satoshi(new Btc(BigDecimal$.MODULE$.apply(fiatAmount).$div(BigDecimal.decimal(rate))))); } /** @@ -291,7 +293,7 @@ public static String formatMsatToFiatWithUnit(final long amountMsat, final Strin public static String formatSatToFiat(final Satoshi amount, final String fiatCode) { final double rate = App.RATES.containsKey(fiatCode) ? App.RATES.get(fiatCode) : -1.0f; if (rate < 0) return NO_FIAT_RATE; - return getFiatFormat().format(package$.MODULE$.satoshi2btc(amount).amount().doubleValue() * rate); + return getFiatFormat().format(package$.MODULE$.satoshi2btc(amount).toDouble() * rate); } public static String formatSatToFiatWithUnit(final Satoshi amount, final String fiatCode) { @@ -323,7 +325,7 @@ public static void printAmountInView(final TextView view, final String amount) { * Return amount as Long, in millisatoshi */ public static long getLongAmountFromInvoice(PaymentRequest paymentRequest) { - return paymentRequest.amount().isEmpty() ? 0 : paymentRequest.amount().get().amount(); + return paymentRequest.amount().isEmpty() ? 0 : paymentRequest.amount().get().toLong(); } public static MilliSatoshi getAmountFromInvoice(PaymentRequest paymentRequest) { diff --git a/app/src/main/res/layout/fragment_receive_payment.xml b/app/src/main/res/layout/fragment_receive_payment.xml index 4a899606..cbd0ef83 100644 --- a/app/src/main/res/layout/fragment_receive_payment.xml +++ b/app/src/main/res/layout/fragment_receive_payment.xml @@ -54,7 +54,7 @@ + type="fr.acinq.eclair.MilliSatoshi" /> @@ -281,7 +281,7 @@ android:paddingTop="@dimen/space_xs" android:paddingEnd="@dimen/space_lg" android:paddingBottom="@dimen/space_sm" - android:visibility="@{!hasNormalChannels || excessiveLightningAmount || maxReceivable.amount == 0 ? View.VISIBLE : View.GONE}" + android:visibility="@{!hasNormalChannels || excessiveLightningAmount || maxReceivable.toLong == 0 ? View.VISIBLE : View.GONE}" app:layout_constrainedWidth="true" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" @@ -320,7 +320,7 @@ android:layout_marginStart="27dp" android:text="@string/receivepayment_lightning_no_inbound" android:textSize="@dimen/text_xs" - android:visibility="@{maxReceivable.amount == 0 ? View.VISIBLE : View.GONE}" /> + android:visibility="@{maxReceivable.toLong == 0 ? View.VISIBLE : View.GONE}" /> Date: Tue, 1 Oct 2019 15:47:08 +0200 Subject: [PATCH 3/6] Get current block height from NodeParams in Channel UI elements --- .../wallet/adapters/LocalChannelItemAdapter.java | 7 +++++-- .../eclair/wallet/adapters/LocalChannelItemHolder.java | 4 ++-- .../eclair/wallet/fragments/ChannelsListFragment.java | 10 ++++++++-- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/fr/acinq/eclair/wallet/adapters/LocalChannelItemAdapter.java b/app/src/main/java/fr/acinq/eclair/wallet/adapters/LocalChannelItemAdapter.java index 2a2bf33d..6149fc32 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/adapters/LocalChannelItemAdapter.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/adapters/LocalChannelItemAdapter.java @@ -25,6 +25,7 @@ import fr.acinq.eclair.CoinUnit; import fr.acinq.eclair.CoinUtils; +import fr.acinq.eclair.wallet.App; import fr.acinq.eclair.wallet.R; import fr.acinq.eclair.wallet.models.LocalChannel; import fr.acinq.eclair.wallet.utils.Constants; @@ -35,9 +36,11 @@ public class LocalChannelItemAdapter extends RecyclerView.Adapter channels) { + public LocalChannelItemAdapter(App.AppKit kit, List channels) { this.channels = channels; + this.appKit = kit; } @Override @@ -48,7 +51,7 @@ public LocalChannelItemHolder onCreateViewHolder(ViewGroup parent, int viewType) @Override public void onBindViewHolder(LocalChannelItemHolder holder, int position) { - holder.bindItem(this.channels.get(position), this.fiatCode, this.prefUnit, this.displayAmountAsFiat); + holder.bindItem(this.appKit, this.channels.get(position), this.fiatCode, this.prefUnit, this.displayAmountAsFiat); } @Override diff --git a/app/src/main/java/fr/acinq/eclair/wallet/adapters/LocalChannelItemHolder.java b/app/src/main/java/fr/acinq/eclair/wallet/adapters/LocalChannelItemHolder.java index d2bc647d..860641e5 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/adapters/LocalChannelItemHolder.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/adapters/LocalChannelItemHolder.java @@ -73,7 +73,7 @@ public void onClick(View v) { } @SuppressLint("SetTextI18n") - protected void bindItem(final LocalChannel item, final String fiatCode, final CoinUnit prefUnit, final boolean displayAmountAsFiat) { + protected void bindItem(final App.AppKit kit, final LocalChannel item, final String fiatCode, final CoinUnit prefUnit, final boolean displayAmountAsFiat) { this.channel = item; node.setText(itemView.getResources().getString(R.string.channelitem_with_node_funder, item.getPeerNodeId())); @@ -110,7 +110,7 @@ protected void bindItem(final LocalChannel item, final String fiatCode, final Co } - Long currentBlockHeight = 123L; //appKit.eclairKit.nodeParams().currentBlockHeight(); + Long currentBlockHeight = kit.eclairKit.nodeParams().currentBlockHeight(); // ---- additional dynamic info, such as delayed closing tx, inflight htlcs... if (CLOSING$.MODULE$.toString().equals(item.state) && ClosingType.LOCAL.equals(item.getClosingType())) { // TODO: get the exact block at which the closing tx will be broadcast diff --git a/app/src/main/java/fr/acinq/eclair/wallet/fragments/ChannelsListFragment.java b/app/src/main/java/fr/acinq/eclair/wallet/fragments/ChannelsListFragment.java index 3549a1f9..26dad54f 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/fragments/ChannelsListFragment.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/fragments/ChannelsListFragment.java @@ -50,8 +50,9 @@ public class ChannelsListFragment extends Fragment { public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(false); - mActiveChannelsAdapter = new LocalChannelItemAdapter(new ArrayList<>()); - mInactiveChannelsAdapter = new LocalChannelItemAdapter(new ArrayList<>()); + App.AppKit kit = getApp() != null ? getApp().appKit : null; + mActiveChannelsAdapter = new LocalChannelItemAdapter(kit, new ArrayList<>()); + mInactiveChannelsAdapter = new LocalChannelItemAdapter(kit, new ArrayList<>()); } @Override @@ -147,4 +148,9 @@ public void run() { } }.start(); } + + private App getApp() { + return (getActivity() != null && getActivity().getApplication() != null) ? (App) getActivity().getApplication() : null; + } + } From 8786980f0eb1429aa8fd74e01bcfcd18b16d9cf2 Mon Sep 17 00:00:00 2001 From: Andrea Raspitzu Date: Tue, 1 Oct 2019 15:50:39 +0200 Subject: [PATCH 4/6] Cleanup imports --- app/src/main/java/fr/acinq/eclair/wallet/App.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/app/src/main/java/fr/acinq/eclair/wallet/App.java b/app/src/main/java/fr/acinq/eclair/wallet/App.java index bb9a6143..379a54f5 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/App.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/App.java @@ -46,10 +46,8 @@ import fr.acinq.eclair.blockchain.electrum.ElectrumClient; import fr.acinq.eclair.blockchain.electrum.ElectrumEclairWallet; import fr.acinq.eclair.blockchain.electrum.ElectrumWallet; -import fr.acinq.eclair.blockchain.fee.FeeEstimator; import fr.acinq.eclair.channel.*; import fr.acinq.eclair.io.Peer; -import fr.acinq.eclair.package$; import fr.acinq.eclair.payment.PaymentInitiator; import fr.acinq.eclair.payment.PaymentLifecycle; import fr.acinq.eclair.payment.PaymentRequest; @@ -74,17 +72,11 @@ import org.slf4j.LoggerFactory; import org.spongycastle.crypto.digests.SHA256Digest; -import scala.Function0; -import scala.Function1; -import scala.Int; -import scala.None; import scala.Option; import scala.Symbol; import scala.Tuple2; -import scala.Unit; import scala.collection.Iterable; import scala.collection.Iterator; -import scala.collection.Seq; import scala.collection.Seq$; import scala.concurrent.Await; import scala.concurrent.Future; From 52b3f769fd9dc510ccdcb7a4f23679fbaada3b9c Mon Sep 17 00:00:00 2001 From: Andrea Raspitzu Date: Tue, 1 Oct 2019 15:53:02 +0200 Subject: [PATCH 5/6] Fix fallback values for fee estimation --- app/src/main/java/fr/acinq/eclair/wallet/App.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/fr/acinq/eclair/wallet/App.java b/app/src/main/java/fr/acinq/eclair/wallet/App.java index 379a54f5..34513443 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/App.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/App.java @@ -527,10 +527,10 @@ public long estimateSlowFees() { } public long estimateMediumFees() { - return Math.max(appKit.eclairKit.nodeParams().onChainFeeConf().feeEstimator().getFeeratePerKb(12) / 1000, 3); } + return Math.max(appKit.eclairKit.nodeParams().onChainFeeConf().feeEstimator().getFeeratePerKb(12) / 1000, estimateSlowFees()); } public long estimateFastFees() { - return Math.max(appKit.eclairKit.nodeParams().onChainFeeConf().feeEstimator().getFeeratePerKb(2) / 1000, 3); } + return Math.max(appKit.eclairKit.nodeParams().onChainFeeConf().feeEstimator().getFeeratePerKb(2) / 1000, estimateMediumFees()); } /** * Asynchronously asks for the Lightning Network's channels count. Dispatch a {@link NetworkChannelsCountEvent} containing the channel count. From abd0f53c78d649bc842b69c196ea248a48a5a191 Mon Sep 17 00:00:00 2001 From: Andrea Raspitzu Date: Tue, 1 Oct 2019 16:26:06 +0200 Subject: [PATCH 6/6] Use nicer "OrElse" to deal with scala's Option --- .../main/java/fr/acinq/eclair/wallet/App.java | 4 +- .../eclair/wallet/utils/TechnicalHelper.java | 65 +++++++++++++++++++ 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/fr/acinq/eclair/wallet/App.java b/app/src/main/java/fr/acinq/eclair/wallet/App.java index 34513443..fa3d8c46 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/App.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/App.java @@ -61,6 +61,7 @@ import fr.acinq.eclair.wallet.events.*; import fr.acinq.eclair.wallet.services.CheckElectrumWorker; import fr.acinq.eclair.wallet.utils.Constants; +import fr.acinq.eclair.wallet.utils.TechnicalHelper; import fr.acinq.eclair.wallet.utils.WalletUtils; import okhttp3.*; import org.greenrobot.eventbus.EventBus; @@ -92,7 +93,6 @@ import java.util.Date; import java.util.HashMap; import java.util.Map; -import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; @@ -280,7 +280,7 @@ public PaymentRequest generatePaymentRequest(final String description, final Opt * If false, can lead the user to pay a lot of fees. */ public void sendLNPayment(final PaymentRequest paymentRequest, final long amountMsat, final boolean checkFees) { - final long finalCltvExpiry = paymentRequest.minFinalCltvExpiryDelta().isDefined() ? paymentRequest.minFinalCltvExpiryDelta().get().toInt() : Channel.MIN_CLTV_EXPIRY_DELTA().toInt(); + final long finalCltvExpiry = paymentRequest.minFinalCltvExpiryDelta().getOrElse(new TechnicalHelper.OrElse<>(Channel.MIN_CLTV_EXPIRY_DELTA().toInt())); final Option routeParams = checkFees ? Option.apply(null) // when fee protection is enabled, use the default RouteParams with reasonable values diff --git a/app/src/main/java/fr/acinq/eclair/wallet/utils/TechnicalHelper.java b/app/src/main/java/fr/acinq/eclair/wallet/utils/TechnicalHelper.java index 9a335ec6..ff52863d 100644 --- a/app/src/main/java/fr/acinq/eclair/wallet/utils/TechnicalHelper.java +++ b/app/src/main/java/fr/acinq/eclair/wallet/utils/TechnicalHelper.java @@ -19,6 +19,8 @@ import android.content.Context; import androidx.annotation.NonNull; import androidx.viewpager.widget.ViewPager; +import scala.Function0; + import android.text.Editable; import android.view.GestureDetector; import android.view.MotionEvent; @@ -154,4 +156,67 @@ public void transformPage(@NonNull View view, float position) { } } + class OrElse implements Function0 { + private T t; + + public OrElse(T someT){ + this.t = someT; + } + + @Override + public T apply() { + return t; + } + + @Override + public String toString() { + return super.toString(); + } + + @Override + public boolean apply$mcZ$sp() { + return false; + } + + @Override + public byte apply$mcB$sp() { + return 0; + } + + @Override + public char apply$mcC$sp() { + return 0; + } + + @Override + public double apply$mcD$sp() { + return 0; + } + + @Override + public float apply$mcF$sp() { + return 0; + } + + @Override + public int apply$mcI$sp() { + return 0; + } + + @Override + public long apply$mcJ$sp() { + return 0; + } + + @Override + public short apply$mcS$sp() { + return 0; + } + + @Override + public void apply$mcV$sp() { + + } + } + }