Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apollo: Release source code for 51.1 #132

Merged
merged 1 commit into from
Oct 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions android/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,38 @@ follow [https://changelog.md/](https://changelog.md/) guidelines.

## [Unreleased]

## [51.1] - 2023-10-17

### ADDED

- Special UI warning message when performing a cyclical payment using the last copied address from
the receive screen.
- Added and enhanced debugging data, specially for notification processing.

### FIXED

- A bug that messed up currency rotation (e.g currencies rotate when clicked upon) in New Operation
screen.
- A bug where duplicated UI events firing in a short range from messing with secure storage's
Keystore.
- Stop polling for notifications upon an ExpiredSession error. Avoid wasting resources and
generating backend alerts.
- A visual glitch in lnurl withdraw unresponsive error handling.
- A bug in lnurl withdraw flow when manually inputting the lnurl in the Send screen.
- A bug where the "Welcome to Muun" dialog would be displayed more than once if the Home activity
was recreated.
- Several memory leaks regarding QRs bitmaps and Repository registry.

### CHANGED

- Special UI component to "paste from clipboard" to adapt to Android's clipboard access notification
on Android 12+. We no longer automatically read from clipboard in Android12+, only upon user
request.
- Satoshis copy in Select Bitcoin Unit screen. Now explicitly naming the option Satoshi (SAT),
instead of Bitcoin (SAT).
- Silence noisy DRM errors.
- Huge revamp to UI test suite. Enhancing reliability o coverage.

## [51] - 2023-07-28

### ADDED
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ package io.muun.apollo.data.analytics
import android.content.Context
import android.content.res.Resources
import android.os.Bundle
import android.util.Log
import com.google.firebase.analytics.FirebaseAnalytics
import io.muun.apollo.domain.analytics.AnalyticsEvent
import io.muun.apollo.domain.model.report.CrashReport
import io.muun.apollo.domain.model.user.User
import timber.log.Timber
import javax.inject.Inject
import javax.inject.Singleton

Expand Down Expand Up @@ -64,7 +64,7 @@ class AnalyticsProvider @Inject constructor(val context: Context) {

fba.logEvent(event.eventId, bundle)
inMemoryMapBreadcrumbCollector[event.eventId] = bundle
Timber.i(event.toString())
Log.i("AnalyticsProvider", event.toString())
}

private fun getBreadcrumbMetadata(): String {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package io.muun.apollo.data.debug

import android.app.Application
import android.os.Debug
import io.muun.apollo.data.external.Globals
import timber.log.Timber
import java.io.IOException

/**
* Utility class to help the debug and analysis of OutOfMemoryError (OOM) and memory leaks. Meant
* to be used ONLY for DEBUG builds.
*/
object HeapDumper {

private lateinit var application: Application

//uncaught exceptions
private var defaultUncaughtExceptionHandler: Thread.UncaughtExceptionHandler? = null

@JvmStatic
fun init(application: Application) {
if (Globals.INSTANCE.isDebugBuild) {
this.application = application
defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler()
Thread.setDefaultUncaughtExceptionHandler(customUncaughtExceptionHandler)
}
}

// OOM handler listener
private val customUncaughtExceptionHandler = Thread.UncaughtExceptionHandler { thread, ex ->
if (ex is OutOfMemoryError) {
try {
Timber.i("DumpHprofData: Starting...")
Debug.dumpHprofData("${application.filesDir.absolutePath}/apollo-oom-dump.hprof")
} catch (e: IOException) {
Timber.i("DumpHprofData: Error: $e. Cause: $ex")
}
Timber.i("DumpHprofData: Success")
}

//call the default exception handler
defaultUncaughtExceptionHandler?.uncaughtException(thread, ex)
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.muun.apollo.presentation.ui.debug
package io.muun.apollo.data.debug

import io.muun.apollo.BuildConfig
import io.muun.apollo.data.external.Globals
import io.muun.common.utils.LnInvoice
import okhttp3.Response
Expand All @@ -18,20 +17,27 @@ class LappClient : SimpleHttpClient() {
EXPIRED_LNURL("expiredLnurl"),
NO_ROUTE("noRoute"),
WRONG_TAG("wrongTag"),
UNRESPONSIVE("unresponsive")
UNRESPONSIVE("unresponsive"),
UNRESPONSIVE_LNURL_SERVICE("unresponsiveLnurlService") // service that generates LNURL
}

private val url = BuildConfig.LAPP_URL
private val url = Globals.INSTANCE.lappUrl

private fun executeNow(request: Observable<Response>): String {
private fun executeNow(request: Observable<Response>): Response {
val response = request.toBlocking().first()!!
return response.body()!!.string()

// Simple error handling will do for now
if (response.code() in 400..599) {
throw LappClientError(response.message() + ": " + response.bodyAsString())
}

return response
}

fun getLnInvoice(amountInSats: Int): LnInvoice {

val request = get("$url/invoice?satoshis=$amountInSats")
val htmlString = executeNow(request)
val htmlString = executeNow(request).bodyAsString()

val invoiceString = htmlString
.substringBefore("</span>")
Expand Down Expand Up @@ -65,21 +71,27 @@ class LappClient : SimpleHttpClient() {
}

/**
* Return a new withdraw LNURL. Receives a variant param to generate different LNRULs to force
* Return a new withdraw LNURL. Receives a variant param to generate different LNURLs to force
* different use cases.
*/
fun generateWithdrawLnUrl(variant: LnUrlVariant = LnUrlVariant.NORMAL): String {

if (variant == LnUrlVariant.UNRESPONSIVE) {
if (variant == LnUrlVariant.UNRESPONSIVE_LNURL_SERVICE) {
// Hard-coded lnurl to force "unresponsive service" response
// Encoded uri is: https://this.domain.does.not.exist.example.com?secret=12345
return "LNURL1DP68GURN8GHJ7ARGD9EJUER0D4SKJM3WV3HK2UEWDEHHGTN90P5HXAPWV4UXZMTSD3JJUC" +
"M0D5LHXETRWFJHG0F3XGENGDGQ8EH52"

}

val request = get("$url/lnurl/withdrawStart?variant=${variant.value}&block=true")
// For SLOW ui tests we need the async behavior of the lapp's lnurl withdraw flow. Otherwise
// Receiving state is never reached (e.g cause the withdraw fullfill request ends after the
// ln payment is completed).
val blocking = variant != LnUrlVariant.SLOW
val request = get("$url/lnurl/withdrawStart?variant=${variant.value}&block=$blocking")
val response = executeNow(request)

return response.trim()
return response.bodyAsString()
}

/**
Expand Down Expand Up @@ -114,4 +126,7 @@ class LappClient : SimpleHttpClient() {
val request = post("$url/undrop?tx=$txId", "")
executeNow(request)
}

private fun Response.bodyAsString(): String =
body()!!.string().trim()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package io.muun.apollo.data.debug

class LappClientError(override val message: String) : RuntimeException()
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.muun.apollo.presentation.ui.debug
package io.muun.apollo.data.debug

import android.os.AsyncTask
import okhttp3.MediaType
Expand Down
Original file line number Diff line number Diff line change
@@ -1,112 +1,119 @@
package io.muun.apollo.data.external;
package io.muun.apollo.data.external

import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.core.NetworkParameters

abstract class Globals {

public abstract class Globals {
companion object {

/**
* This will be initialized in the UI application code, since it depends on Android build
* configurations.
*/
public static Globals INSTANCE;
/**
* This will be initialized in the UI application code, since it depends on Android build
* configurations.
*/
lateinit var INSTANCE: Globals
}

/**
* Get the Application Id (previously package name) of the app. Identifies the app on the
* device, its unique in the Google Play store.
*/
public abstract String getApplicationId();
abstract val applicationId: String

/**
* Get whether the current build a debuggable build.
*/
public abstract boolean isDebugBuild();
abstract val isDebugBuild: Boolean

/**
* Get the build type of the current build.
*/
public abstract String getBuildType();
abstract val buildType: String

/**
* Get the legacy build type of the current build. It is now deprecated in favour of
* {@link Globals#getBuildType()}.
* [Globals.buildType].
*/
public abstract String getOldBuildType();
abstract val oldBuildType: String

/**
* Get the version code of the current build (e.g 1004).
*/
public abstract int getVersionCode();
abstract val versionCode: Int

/**
* Get the version name of the current build (e.g 50.4).
*/
public abstract String getVersionName();
abstract val versionName: String

/**
* Get the version name of the current build (e.g 50.4).
*/
public abstract String getDeviceName();
abstract val deviceName: String

/**
* Get the model name of the device where app is running.
*/
public abstract String getDeviceModel();
abstract val deviceModel: String

/**
* Get the manufacturer name of the device where app is running.
*/
public abstract String getDeviceManufacturer();
abstract val deviceManufacturer: String

/**
* Get the fingerprint of the device where app is running.
*/
public abstract String getFingerprint();
abstract val fingerprint: String

/**
* Get the hardware name of the device where app is running.
*/
public abstract String getHardware();
abstract val hardware: String

/**
* Get the bootloader name of the device where app is running.
*/
public abstract String getBootloader();
abstract val bootloader: String

/**
* Get the bitcoin network specs/parameters of the network this build is using.
*/
public abstract NetworkParameters getNetwork();
abstract val network: NetworkParameters

/**
* Get the hostname of this app's deeplink.
*/
public abstract String getMuunLinkHost();
abstract val muunLinkHost: String

/**
* Get the path of this app's "Verify" deeplink.
*/
public abstract String getVerifyLinkPath();
abstract val verifyLinkPath: String

/**
* Get the path of this app's "Authorize" deeplink.
*/
public abstract String getAuthorizeLinkPath();
abstract val authorizeLinkPath: String

/**
* Get the path of this app's "Confirm" deeplink.
*/
public abstract String getConfirmLinkPath();
abstract val confirmLinkPath: String

/**
* Get the path of this app's "Authorize RC Login" deeplink.
*/
public abstract String getRcLoginAuthorizePath();
abstract val rcLoginAuthorizePath: String

/**
* Get Lapp's URL.
*/
abstract val lappUrl: String

/**
* Get whether the current build is a release build.
*/
public boolean isReleaseBuild() {
return getBuildType().equals("release");
}
}
val isReleaseBuild: Boolean
get() = buildType == "release"

}
Loading
Loading