Skip to content
Open
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
4 changes: 2 additions & 2 deletions .github/workflows/build-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ on:

jobs:
build-release:
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # Matches tag v3.0.0
Expand Down Expand Up @@ -41,7 +41,7 @@ jobs:

with:
name: apk
path: apk/apolloui-prod-release-unsigned.apk
path: apk/apolloui-prod-*-release-unsigned.apk

- name: Upload mapping
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # Matches tag v4.3.3
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on: pull_request

jobs:
pr:
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # Matches tag v3.0.0
Expand Down Expand Up @@ -42,4 +42,4 @@ jobs:

with:
name: apk
path: apk/apolloui-prod-release-unsigned.apk
path: apk/apolloui-prod-*-release-unsigned.apk
29 changes: 29 additions & 0 deletions android/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,35 @@ follow [https://changelog.md/](https://changelog.md/) guidelines.

## [Unreleased]

## [53.4] - 2025-05-29

### CHANGED

- Added multi APK support to bypass 100MB APK size limit.

## [53.3] - 2025-04-08

### FIXED

- Proper fix for non ascii chars in http headers

## [53.2] - 2025-03-24

### ADDED

- Alternative transactions signing

## [53.1] - 2025-02-21

### ADDED

- Revamped real time fees calculation
- Background notification processing reliability improvements

### FIXED

- Non deterministic bug regarding hardened key derivation

## [52.7] - 2025-01-30

### ADDED
Expand Down
5 changes: 4 additions & 1 deletion android/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -67,5 +67,8 @@ RUN tools/bootstrap-gomobile.sh \

FROM scratch

COPY --from=build /src/android/apolloui/build/outputs/apk/prod/release/apolloui-prod-release-unsigned.apk apolloui-prod-release-unsigned.apk
COPY --from=build /src/android/apolloui/build/outputs/apk/prod/release/apolloui-prod-arm64-v8a-release-unsigned.apk apolloui-prod-arm64-v8a-release-unsigned.apk
COPY --from=build /src/android/apolloui/build/outputs/apk/prod/release/apolloui-prod-armeabi-v7a-release-unsigned.apk apolloui-prod-armeabi-v7a-release-unsigned.apk
COPY --from=build /src/android/apolloui/build/outputs/apk/prod/release/apolloui-prod-x86-release-unsigned.apk apolloui-prod-x86-release-unsigned.apk
COPY --from=build /src/android/apolloui/build/outputs/apk/prod/release/apolloui-prod-x86_64-release-unsigned.apk apolloui-prod-x86_64-release-unsigned.apk
COPY --from=build /src/android/apolloui/build/outputs/mapping/prodRelease/mapping.txt mapping.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,9 @@ fun MuunZonedDateTime?.toApolloModel(): ZonedDateTime? {
(this as ApolloZonedDateTime).dateTime
}
}

fun String.toSafeAscii() =
this.map { if (it.code > 127) "$UNICODE_PREFIX${it.code.toString(16).padStart(4, '0')}" else it }
.joinToString("")

private const val UNICODE_PREFIX = "\\u"
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import io.muun.apollo.data.os.execution.ExecutionTransformerFactory;
import io.muun.apollo.data.os.execution.JobExecutor;
import io.muun.apollo.data.preferences.RepositoryRegistry;
import io.muun.apollo.data.preferences.UserRepository;
import io.muun.apollo.domain.action.NotificationActions;
import io.muun.apollo.domain.action.NotificationPoller;
import io.muun.apollo.domain.libwallet.GoLibwalletService;
Expand Down Expand Up @@ -47,7 +48,7 @@ public class DataModule {
private final Func3<
Context,
ExecutionTransformerFactory,
RepositoryRegistry,
UserRepository,
NotificationService
>
notificationServiceFactory;
Expand All @@ -64,7 +65,7 @@ public DataModule(
Func3<
Context,
ExecutionTransformerFactory,
RepositoryRegistry,
UserRepository,
NotificationService
> notificationServiceFactory,
Func1<Context, AppStandbyBucketProvider> appStandbyBucketProviderFactory,
Expand Down Expand Up @@ -127,9 +128,13 @@ DaoManager provideDaoManager(
NotificationService provideNotificationService(
Context context,
ExecutionTransformerFactory executionTransformerFactory,
RepositoryRegistry repoRegistry
UserRepository userRepository
) {
return notificationServiceFactory.call(context, executionTransformerFactory, repoRegistry);
return notificationServiceFactory.call(
context,
executionTransformerFactory,
userRepository
);
}

@Provides
Expand Down
10 changes: 7 additions & 3 deletions android/apollo/src/main/java/io/muun/apollo/data/external/Gen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import io.muun.apollo.data.preferences.stored.StoredEkVerificationCodes
import io.muun.apollo.domain.model.BitcoinAmount
import io.muun.apollo.domain.model.Contact
import io.muun.apollo.domain.model.ExchangeRateWindow
import io.muun.apollo.domain.model.FeeBumpFunctions
import io.muun.apollo.domain.model.FeeWindow
import io.muun.apollo.domain.model.ForwardingPolicy
import io.muun.apollo.domain.model.IncomingSwap
Expand Down Expand Up @@ -273,9 +274,12 @@ object Gen {
* Get a FeeBumpFunctions vector
*/
fun feeBumpFunctions() =
listOf(
"QsgAAAAAAAAAAAAAf4AAAD+AAABAAAAA", // [[100, 0, 0], [+Inf, 1, 2]]
"f4AAAD+AAAAAAAAA" // [[+Inf, 1, 0]]]
FeeBumpFunctions(
"idTest",
listOf(
"QsgAAAAAAAAAAAAAf4AAAD+AAABAAAAA", // [[100, 0, 0], [+Inf, 1, 2]]
"f4AAAD+AAAAAAAAA" // [[+Inf, 1, 0]]]
)
)
/**
* Get a Transaction Hash.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import io.muun.apollo.data.os.GooglePlayServicesHelper;
import io.muun.apollo.data.os.PackageManagerInfoProvider;
import io.muun.apollo.data.serialization.dates.ApolloZonedDateTime;
import io.muun.apollo.domain.libwallet.FeeBumpRefreshPolicy;
import io.muun.apollo.domain.libwallet.Invoice;
import io.muun.apollo.domain.model.BackgroundEvent;
import io.muun.apollo.domain.model.BitcoinAmount;
Expand Down Expand Up @@ -44,9 +45,9 @@
import io.muun.common.api.PhoneNumberJson;
import io.muun.common.api.PublicKeyJson;
import io.muun.common.api.PublicProfileJson;
import io.muun.common.api.RealTimeFeesRequestJson;
import io.muun.common.api.StartEmailSetupJson;
import io.muun.common.api.SubmarineSwapRequestJson;
import io.muun.common.api.UnconfirmedOutpointsJson;
import io.muun.common.api.UserInvoiceJson;
import io.muun.common.api.UserProfileJson;
import io.muun.common.crypto.ChallengePublicKey;
Expand All @@ -62,6 +63,7 @@
import io.muun.common.utils.BitcoinUtils;
import io.muun.common.utils.Encodings;
import io.muun.common.utils.Pair;
import io.muun.common.utils.Preconditions;

import android.os.SystemClock;
import androidx.annotation.NonNull;
Expand Down Expand Up @@ -143,16 +145,25 @@ private BitcoinAmountJson mapBitcoinAmount(@NotNull BitcoinAmount bitcoinAmount)
public OperationJson mapOperation(
final @NotNull OperationWithMetadata operation,
final List<String> outpoints,
final MusigNonces musigNonces
final MusigNonces musigNonces,
final List<MusigNonces> alternativeTxNonces
) {

final Long outputAmountInSatoshis = mapOutputAmountInSatoshis(operation);

final List<String> userPublicNoncesHex = new LinkedList<>();
for (int i = 0; i < outpoints.size(); i++) {
final long noncesCount = musigNonces.length();
for (int i = 0; i < noncesCount; i++) {
userPublicNoncesHex.add(musigNonces.getPubnonceHex(i));
}

for (final MusigNonces nonces : alternativeTxNonces) {
Preconditions.checkState(noncesCount == nonces.length());
for (int i = 0; i < noncesCount; i++) {
userPublicNoncesHex.add(nonces.getPubnonceHex(i));
}
}

return new OperationJson(
UUID.randomUUID().toString(),
operation.getDirection(),
Expand Down Expand Up @@ -232,7 +243,9 @@ public ClientJson mapClient(
final long appSize,
final List<String> hardwareAddresses,
final String vbMeta,
final String efsCreationTimeInSeconds
final String efsCreationTimeInSeconds,
final Boolean isLowRamDevice,
final Long firstInstallTimeInMs
) {
return new ClientJson(
ClientTypeJson.APOLLO,
Expand Down Expand Up @@ -278,7 +291,9 @@ public ClientJson mapClient(
appSize,
hardwareAddresses,
vbMeta,
efsCreationTimeInSeconds
efsCreationTimeInSeconds,
isLowRamDevice,
firstInstallTimeInMs
);
}

Expand Down Expand Up @@ -415,7 +430,9 @@ public CreateFirstSessionJson mapCreateFirstSession(
final Long appSize,
final List<String> hardwareAddresses,
final String vbMeta,
final String efsCreationTimeInSeconds
final String efsCreationTimeInSeconds,
final Boolean isLowRamDevice,
final Long firstInstallTimeInMs
) {

return new CreateFirstSessionJson(
Expand All @@ -442,7 +459,10 @@ public CreateFirstSessionJson mapCreateFirstSession(
appSize,
hardwareAddresses,
vbMeta,
efsCreationTimeInSeconds
efsCreationTimeInSeconds,
isLowRamDevice,
firstInstallTimeInMs

),
gcmToken,
primaryCurrency,
Expand Down Expand Up @@ -479,7 +499,9 @@ public CreateLoginSessionJson mapCreateLoginSession(
final Long appSize,
final List<String> hardwareAddresses,
final String vbMeta,
final String efsCreationTimeInSeconds
final String efsCreationTimeInSeconds,
final Boolean isLowRamDevice,
final Long firstInstallTimeInMs
) {

return new CreateLoginSessionJson(
Expand All @@ -506,7 +528,9 @@ public CreateLoginSessionJson mapCreateLoginSession(
appSize,
hardwareAddresses,
vbMeta,
efsCreationTimeInSeconds
efsCreationTimeInSeconds,
isLowRamDevice,
firstInstallTimeInMs
),
gcmToken,
email
Expand Down Expand Up @@ -541,7 +565,9 @@ public CreateRcLoginSessionJson mapCreateRcLoginSession(
final Long appSize,
final List<String> hardwareAddresses,
final String vbMeta,
final String efsCreationTimeInSeconds
final String efsCreationTimeInSeconds,
final Boolean isLowRamDevice,
final Long firstInstallTimeInMs
) {

return new CreateRcLoginSessionJson(
Expand All @@ -568,7 +594,9 @@ public CreateRcLoginSessionJson mapCreateRcLoginSession(
appSize,
hardwareAddresses,
vbMeta,
efsCreationTimeInSeconds
efsCreationTimeInSeconds,
isLowRamDevice,
firstInstallTimeInMs
),
gcmToken,
new ChallengeKeyJson(
Expand Down Expand Up @@ -771,11 +799,12 @@ private ExportEmergencyKitJson.Method mapExportMethod(
}

/**
* Creates a UnconfirmedOutpointsJson.
* Creates a RealTimeFeesRequestJson.
*/
@NotNull
public UnconfirmedOutpointsJson mapUnconfirmedOutpointsJson(
@NotNull List<SizeForAmount> sizeProgression
public RealTimeFeesRequestJson mapRealTimeFeesRequestJson(
@NotNull List<SizeForAmount> sizeProgression,
@NotNull FeeBumpRefreshPolicy feeBumpRefreshPolicy
) {
final List<String> unconfirmedUtxos = new ArrayList<>();

Expand All @@ -784,7 +813,28 @@ public UnconfirmedOutpointsJson mapUnconfirmedOutpointsJson(
unconfirmedUtxos.add(sizeForAmount.outpoint);
}
}
;
return new RealTimeFeesRequestJson(
unconfirmedUtxos,
mapFeeBumpRefreshPolicy(feeBumpRefreshPolicy)
);
}

return new UnconfirmedOutpointsJson(unconfirmedUtxos);
@NotNull
private RealTimeFeesRequestJson.FeeBumpRefreshPolicy mapFeeBumpRefreshPolicy(
@NotNull FeeBumpRefreshPolicy feeBumpRefreshPolicy
) {
switch (feeBumpRefreshPolicy) {
case PERIODIC:
return RealTimeFeesRequestJson.FeeBumpRefreshPolicy.PERIODIC;
case FOREGROUND:
return RealTimeFeesRequestJson.FeeBumpRefreshPolicy.FOREGROUND;
case NTS_CHANGED:
return RealTimeFeesRequestJson.FeeBumpRefreshPolicy.CHANGED_NEXT_TRANSACTION_SIZE;
case NEW_OP_BLOCKINGLY:
return RealTimeFeesRequestJson.FeeBumpRefreshPolicy.NEW_OPERATION;
default:
throw new MissingCaseError(feeBumpRefreshPolicy);
}
}
}
Loading