Skip to content

Commit

Permalink
Apollo: Release source code for 51.1
Browse files Browse the repository at this point in the history
  • Loading branch information
acrespo committed Oct 19, 2023
1 parent 69bacfb commit cce2fcf
Show file tree
Hide file tree
Showing 131 changed files with 1,977 additions and 1,139 deletions.
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

0 comments on commit cce2fcf

Please sign in to comment.