Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 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
20 changes: 20 additions & 0 deletions .github/workflows/android-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -201,12 +201,32 @@ jobs:
echo "versionName $VERSION_NAME is covered by production bundle $CURRENT"
fi

- name: Write MeaWallet config
# mea_config for the MPP SDK (Google Pay push provisioning) —
# gitignored; bundled from res/raw when present, no-op until the
# secret is provisioned.
env:
MEA_CONFIG: ${{ secrets.MEAWALLET_CONFIG_BASE64 }}
run: |
if [ -n "$MEA_CONFIG" ]; then
mkdir -p android/app/src/main/res/raw
echo "$MEA_CONFIG" | base64 -d > android/app/src/main/res/raw/mea_config
echo "mea_config written"
else
echo "MEAWALLET_CONFIG_BASE64 not set — push provisioning stays stubbed"
fi

- name: Build signed AAB
env:
# native sentry sdk dsn — read by android/app/build.gradle into a
# manifest placeholder. same project dsn the js layer bakes into
# the static export above; no new secret needed.
SENTRY_DSN_ANDROID: ${{ secrets.NEXT_PUBLIC_SENTRY_DSN }}
# MeaWallet MPP SDK — gradle gates both the dependency and the
# plugin source on these; absent secrets build without the SDK.
# Android-specific names: see the note in ios-release.yml.
MEAWALLET_NEXUS_USER: ${{ secrets.MEAWALLET_NEXUS_USER_ANDROID }}
MEAWALLET_NEXUS_PASSWORD: ${{ secrets.MEAWALLET_NEXUS_PASSWORD_ANDROID }}
ANDROID_VERSION_NAME: ${{ steps.version.outputs.name }}
run: |
# Monotonic (run_number always increases). +10000 clears legacy
Expand Down
23 changes: 23 additions & 0 deletions .github/workflows/ios-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -197,13 +197,36 @@ jobs:

- name: Build web + sync iOS
env:
# MeaWallet MPP SDK (Apple Pay push provisioning): postsync
# vendors the xcframework only when these are set, so the
# build stays green until the secrets are provisioned.
# MeaWallet issues separate iOS and Android Nexus credentials,
# and an Environment secret holds one value per name — sharing
# a name would send whichever pair was configured last to both
# platforms and fail the other one's SDK download.
MEAWALLET_NEXUS_USER: ${{ secrets.MEAWALLET_NEXUS_USER_IOS }}
MEAWALLET_NEXUS_PASSWORD: ${{ secrets.MEAWALLET_NEXUS_PASSWORD_IOS }}
# postsync stamps project.pbxproj; without this it would stamp
# package.json's version, which no longer tracks releases.
IOS_MARKETING_VERSION: ${{ steps.version.outputs.name }}
run: |
node scripts/native-build.js && npx cap sync ios
if [ -f scripts/native-ios-postsync.js ]; then node scripts/native-ios-postsync.js; fi

- name: Write MeaWallet config
# mea_config (encrypted, non-sensitive per MeaWallet, but kept out
# of git) — the Copy MeaWallet Config build phase bundles it when
# present; no-op until the secret is provisioned.
env:
MEA_CONFIG: ${{ secrets.MEAWALLET_CONFIG_BASE64 }}
run: |
if [ -n "$MEA_CONFIG" ]; then
echo "$MEA_CONFIG" | base64 -d > ios/App/App/mea_config
echo "mea_config written"
else
echo "MEAWALLET_CONFIG_BASE64 not set — push provisioning stays stubbed"
fi

- name: Install Apple distribution certificate
uses: apple-actions/import-codesign-certs@5142e029c445c10ffc7149d172e540235a065466 # v7
with:
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@ e2e/.auth/
keystore.properties
.env.production.local

# meawallet mpp sdk — credential-gated artifacts + encrypted config, never committed
ios/App/CapApp-SPM/Frameworks/
ios/App/App/mea_config
android/app/src/main/res/raw/mea_config

# capgo ota signing keys — private key is a CI secret; public key lives in capacitor.config.ts
.capgo_key_v2
.capgo_key_v2.pub
Expand Down
21 changes: 21 additions & 0 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,27 @@ repositories {
}
}

/*
* MeaWallet MPP SDK (Google Pay push provisioning) — credential-gated.
* The artifact lives on MeaWallet's private Nexus (repo declared in the root
* build.gradle), so both the dependency and PushProvisioningPlugin.java (in
* src/meawallet/java) are compiled only when credentials are present — CI
* release builds and devs who fetched the 1Password credentials. Without them
* the build stays green and MainActivity's reflection lookup of the plugin
* silently no-ops, so the web layer falls back to the manual carousel.
*/
def meaWalletCreds = System.getenv('MEAWALLET_NEXUS_USER') ?: (findProperty('MEAWALLET_NEXUS_USER') ?: null)
if (meaWalletCreds) {
Comment thread
innolope-dev marked this conversation as resolved.
Outdated
logger.lifecycle('[meawallet] Nexus credentials present — MPP SDK enabled')
android.sourceSets.main.java.srcDirs += 'src/meawallet/java'
dependencies {
debugImplementation 'com.meawallet:mpp-prod:2.1.0-debug'
releaseImplementation 'com.meawallet:mpp-prod:2.1.0'
}
} else {
logger.lifecycle('[meawallet] no Nexus credentials — building without MPP SDK (push provisioning stubbed)')
}

dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
Expand Down
26 changes: 26 additions & 0 deletions android/app/src/main/java/me/peanut/wallet/MainActivity.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package me.peanut.wallet;

import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
import android.webkit.WebResourceRequest;
Expand All @@ -16,6 +17,30 @@

public class MainActivity extends BridgeActivity {

/*
* PushProvisioningPlugin compiles only when the MeaWallet Nexus credentials
* were present at build time (src/meawallet/java, see app/build.gradle), so
* both the registration and the Google Pay activity-result forward go
* through reflection — a build without the SDK must run exactly as before.
*/
private void registerPushProvisioningPlugin() {
try {
registerPlugin(Class.forName("me.peanut.wallet.PushProvisioningPlugin")
.asSubclass(com.getcapacitor.Plugin.class));
} catch (Exception ignored) {}
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
try {
Object handled = Class.forName("me.peanut.wallet.PushProvisioningPlugin")
.getMethod("handleGooglePayActivityResult", int.class, int.class, Intent.class, android.app.Activity.class)
.invoke(null, requestCode, resultCode, data, this);
if (Boolean.TRUE.equals(handled)) return;
} catch (Exception ignored) {}
super.onActivityResult(requestCode, resultCode, data);
}

private void maybeSentryTestCrash() {
if (getIntent() == null || !getIntent().getBooleanExtra("sentry_test_crash", false)) return;
if (getReferrer() != null) return; // app-to-app starts always carry a referrer; adb doesn't
Expand All @@ -32,6 +57,7 @@ private void maybeSentryTestCrash() {
protected void onCreate(Bundle savedInstanceState) {
// app-local plugin, not auto-discovered — must register before super.onCreate
registerPlugin(InstallReferrerPlugin.class);
registerPushProvisioningPlugin();
super.onCreate(savedInstanceState);

/*
Expand Down
Loading
Loading