forked from github-such-software/hash-wallet
Compare commits
6 Commits
771938e545
...
f1d6f165ea
| Author | SHA1 | Date | |
|---|---|---|---|
| f1d6f165ea | |||
|
|
c7f64f8273 | ||
|
|
6304521e92 | ||
|
|
083f8b7f2a | ||
|
|
360556b8f7 | ||
|
|
1098a1a017 |
228
.github/workflows/build-android.yml
vendored
Normal file
228
.github/workflows/build-android.yml
vendored
Normal file
@@ -0,0 +1,228 @@
|
||||
name: Hash Wallet Android build
|
||||
|
||||
# Triggers:
|
||||
# - push to dev/main (validate every commit)
|
||||
# - PRs targeting dev/main (gate merges)
|
||||
# - manual via workflow_dispatch
|
||||
on:
|
||||
push:
|
||||
branches: [dev, main]
|
||||
pull_request:
|
||||
branches: [dev, main]
|
||||
workflow_dispatch:
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
# Same Cake-Labs prebuilt image used for Linux. Bundles Flutter 3.32.0,
|
||||
# Android NDK r28, Go 1.24.1, Android SDK, JDK 17, gradle, and the
|
||||
# native build deps (boost, openssl, libsodium, libzmq, unbound, icu).
|
||||
image: ghcr.io/cake-tech/cake_wallet:debian13-flutter3.32.0-ndkr28-go1.24.1-ruststablenightly
|
||||
env:
|
||||
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
|
||||
APP_ANDROID_TYPE: cakewallet
|
||||
|
||||
steps:
|
||||
- name: Fix Actions HOME (writeable for ~/.cache + gradle)
|
||||
run: echo "HOME=/root" >> $GITHUB_ENV
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Configure git inside the container
|
||||
run: |
|
||||
git config --global --add safe.directory '*'
|
||||
git config --global user.email "ci@suchsoftware.com"
|
||||
git config --global user.name "Hash Wallet CI"
|
||||
|
||||
# ---- External prebuilt deps (same approach as Linux workflow) --------
|
||||
- name: Fetch prebuilt torch_dart
|
||||
run: |
|
||||
set -x -e
|
||||
pushd scripts
|
||||
rm -rf torch_dart torch_dart.tar.gz
|
||||
wget -q https://github.com/MrCyjaneK/torch_dart/releases/download/v1.0.17/torch_dart-v1.0.17.tar.gz -O torch_dart.tar.gz
|
||||
mkdir torch_dart
|
||||
tar -xzf torch_dart.tar.gz -C torch_dart
|
||||
rm torch_dart.tar.gz
|
||||
popd
|
||||
|
||||
- name: Fetch prebuilt reown_flutter
|
||||
run: |
|
||||
set -x -e
|
||||
pushd scripts
|
||||
rm -rf reown_flutter reown_flutter.tar.gz
|
||||
wget -q https://github.com/cake-tech/reown_flutter/releases/download/v0.0.4/reown_flutter-v0.0.4.tar.gz -O reown_flutter.tar.gz
|
||||
mkdir reown_flutter
|
||||
tar -xzf reown_flutter.tar.gz -C reown_flutter
|
||||
rm reown_flutter.tar.gz
|
||||
popd
|
||||
|
||||
- name: Clone BitBox Flutter
|
||||
run: |
|
||||
set -x -e
|
||||
pushd scripts
|
||||
./build_bitbox_flutter.sh
|
||||
popd
|
||||
|
||||
# ---- Native crypto cores (monero_c prebuilt bundle) ------------------
|
||||
# Same release-bundle.zip as Linux. Contains pre-cross-compiled .so
|
||||
# files for monero/wownero/zano across all 4 Android ABIs. We only ship
|
||||
# monero + wownero — zano libs in the bundle are ignored.
|
||||
- name: Fetch prebuilt monero_c .so bundle
|
||||
run: |
|
||||
set -x -e
|
||||
./scripts/prepare_moneroc.sh
|
||||
MONERO_C_TAG=$(cd scripts/monero_c && git describe --tags)
|
||||
echo "monero_c TAG: $MONERO_C_TAG"
|
||||
mkdir -p "scripts/monero_c/release/$MONERO_C_TAG"
|
||||
pushd "scripts/monero_c/release/$MONERO_C_TAG"
|
||||
wget -q https://github.com/MrCyjaneK/monero_c/releases/download/v0.18.4.6-RC1/release-bundle.zip
|
||||
unzip -q release-bundle.zip
|
||||
rm release-bundle.zip
|
||||
ls
|
||||
popd
|
||||
|
||||
# ---- Stage native libs into android/app/src/main/jniLibs/<ABI>/ -----
|
||||
# Flutter Android packaging auto-includes everything under jniLibs.
|
||||
- name: Place Android .so files into jniLibs
|
||||
run: |
|
||||
set -x -e
|
||||
MONERO_C_TAG=$(cd scripts/monero_c && git describe --tags)
|
||||
BUNDLE_DIR="scripts/monero_c/release/$MONERO_C_TAG"
|
||||
|
||||
# monero_c target dir → Android ABI dir
|
||||
declare -A ABI_MAP=(
|
||||
[aarch64-linux-android]=arm64-v8a
|
||||
[armv7a-linux-androideabi]=armeabi-v7a
|
||||
[i686-linux-android]=x86
|
||||
[x86_64-linux-android]=x86_64
|
||||
)
|
||||
|
||||
for target in "${!ABI_MAP[@]}"; do
|
||||
abi="${ABI_MAP[$target]}"
|
||||
mkdir -p "android/app/src/main/jniLibs/$abi"
|
||||
for coin in monero wownero; do
|
||||
src="$BUNDLE_DIR/$target/lib${coin}_wallet2_api_c.so"
|
||||
if [[ -f "$src" ]]; then
|
||||
cp -v "$src" "android/app/src/main/jniLibs/$abi/"
|
||||
else
|
||||
echo "MISSING: $src — fail loud, the bundle layout may have changed"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
echo "=== jniLibs contents ==="
|
||||
find android/app/src/main/jniLibs/ -type f -name '*.so' | sort
|
||||
|
||||
# mwebd (Litecoin MWEB) is NOT built here. LTC works without MWEB —
|
||||
# users just don't get the privacy MWEB feature. Add a build_mwebd
|
||||
# step if/when we want MWEB on Android.
|
||||
|
||||
# ---- Configure: pubspec.yaml, AndroidManifest.xml, app_properties ----
|
||||
- name: Run Android configure (cakewallet profile)
|
||||
run: |
|
||||
set -x -e
|
||||
pushd scripts/android
|
||||
source ./app_env.sh cakewallet
|
||||
./app_config.sh
|
||||
popd
|
||||
|
||||
# ---- Secrets ---------------------------------------------------------
|
||||
- name: Generate per-module secrets.g.dart files (all empty defaults)
|
||||
run: dart run tool/generate_new_secrets.dart
|
||||
|
||||
- name: Inject Trocador affiliate secrets into lib/.secrets.g.dart
|
||||
env:
|
||||
TROCADOR_API_KEY: ${{ secrets.TROCADOR_API_KEY }}
|
||||
TROCADOR_MONERO_API_KEY: ${{ secrets.TROCADOR_MONERO_API_KEY }}
|
||||
TROCADOR_EXCHANGE_MARKUP: ${{ secrets.TROCADOR_EXCHANGE_MARKUP }}
|
||||
run: |
|
||||
sed -i \
|
||||
-e "s|const trocadorApiKey = '';|const trocadorApiKey = '${TROCADOR_API_KEY}';|" \
|
||||
-e "s|const trocadorMoneroApiKey = '';|const trocadorMoneroApiKey = '${TROCADOR_MONERO_API_KEY}';|" \
|
||||
-e "s|const trocadorExchangeMarkup = '';|const trocadorExchangeMarkup = '${TROCADOR_EXCHANGE_MARKUP:-1}';|" \
|
||||
lib/.secrets.g.dart
|
||||
grep '^const trocador' lib/.secrets.g.dart
|
||||
|
||||
# ---- Signing: decode upload keystore + write key.properties ---------
|
||||
- name: Decode Android upload keystore + write key.properties
|
||||
env:
|
||||
ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
|
||||
ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
|
||||
ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
|
||||
ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
|
||||
run: |
|
||||
set -e
|
||||
if [[ -z "$ANDROID_KEYSTORE_BASE64" ]]; then
|
||||
echo "FATAL: ANDROID_KEYSTORE_BASE64 not set — configure Gitea Actions secrets first"
|
||||
exit 1
|
||||
fi
|
||||
# Write decoded keystore next to build.gradle (storeFile path
|
||||
# in key.properties is resolved relative to android/app/).
|
||||
echo "$ANDROID_KEYSTORE_BASE64" | base64 -d > android/app/upload-keystore.jks
|
||||
ls -la android/app/upload-keystore.jks
|
||||
# key.properties consumed by build.gradle's signingConfigs.release.
|
||||
cat > android/key.properties <<EOF
|
||||
storePassword=$ANDROID_KEYSTORE_PASSWORD
|
||||
keyPassword=$ANDROID_KEY_PASSWORD
|
||||
keyAlias=$ANDROID_KEY_ALIAS
|
||||
storeFile=upload-keystore.jks
|
||||
EOF
|
||||
chmod 600 android/key.properties
|
||||
|
||||
# ---- Flutter SDK init + codegen --------------------------------------
|
||||
- name: Initialize Flutter SDK (Android precache)
|
||||
run: |
|
||||
flutter --version
|
||||
flutter precache --android --no-linux --no-ios --no-macos --no-windows --no-fuchsia --no-web || true
|
||||
|
||||
- name: Build generated code (mobx + hive adapters)
|
||||
run: bash model_generator.sh
|
||||
|
||||
- name: Generate localization
|
||||
run: dart run tool/generate_localization.dart
|
||||
|
||||
# ---- Compile + sign --------------------------------------------------
|
||||
# Universal APK (single binary covers all 4 ABIs, easy to sideload).
|
||||
- name: Build release APK (universal, all ABIs)
|
||||
run: flutter build apk --dart-define-from-file=env.json --release
|
||||
|
||||
# AAB for Play Console upload (Google generates per-ABI APKs server-side
|
||||
# via Play App Signing).
|
||||
- name: Build release AAB
|
||||
run: flutter build appbundle --dart-define-from-file=env.json --release
|
||||
|
||||
- name: Sanity-check signature on APK
|
||||
run: |
|
||||
set -x
|
||||
ls -la build/app/outputs/flutter-apk/
|
||||
# apksigner is in build-tools; locate dynamically.
|
||||
APKSIGNER=$(find $ANDROID_HOME/build-tools -name apksigner -type f 2>/dev/null | sort -V | tail -1 || which apksigner)
|
||||
if [[ -n "$APKSIGNER" ]]; then
|
||||
"$APKSIGNER" verify --print-certs build/app/outputs/flutter-apk/app-release.apk || true
|
||||
else
|
||||
echo "apksigner not on PATH; skipping sig print"
|
||||
fi
|
||||
|
||||
# actions/upload-artifact@v4 doesn't work on Gitea; pin to v3.
|
||||
- name: Upload APK artifact (sideload-able)
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: hash-wallet-android-apk-${{ github.sha }}
|
||||
path: build/app/outputs/flutter-apk/app-release.apk
|
||||
retention-days: 14
|
||||
|
||||
- name: Upload AAB artifact (for Play Console)
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: hash-wallet-android-aab-${{ github.sha }}
|
||||
path: build/app/outputs/bundle/release/app-release.aab
|
||||
retention-days: 30
|
||||
164
.github/workflows/build-ios-sim.yml
vendored
Normal file
164
.github/workflows/build-ios-sim.yml
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
name: Hash Wallet iOS Simulator build
|
||||
|
||||
# Phase 1 of iOS CI: validate the Mac runner end-to-end by producing an
|
||||
# unsigned simulator .app. Drop the resulting Runner.app into the iOS
|
||||
# Simulator on any Apple Silicon Mac to verify the app actually compiles
|
||||
# and launches.
|
||||
#
|
||||
# Phase 2 (separate workflow): full TestFlight pipeline with signing.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [dev, main]
|
||||
pull_request:
|
||||
branches: [dev, main]
|
||||
workflow_dispatch:
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: macos-latest
|
||||
env:
|
||||
APP_IOS_TYPE: cakewallet
|
||||
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Show toolchain
|
||||
run: |
|
||||
set -x
|
||||
flutter --version
|
||||
xcodebuild -version
|
||||
pod --version
|
||||
which wget unzip
|
||||
uname -m
|
||||
|
||||
# ---- External prebuilt deps (same as android/linux) ------------------
|
||||
- name: Fetch prebuilt torch_dart
|
||||
run: |
|
||||
set -x -e
|
||||
pushd scripts
|
||||
rm -rf torch_dart torch_dart.tar.gz
|
||||
wget -q https://github.com/MrCyjaneK/torch_dart/releases/download/v1.0.17/torch_dart-v1.0.17.tar.gz -O torch_dart.tar.gz
|
||||
mkdir torch_dart
|
||||
tar -xzf torch_dart.tar.gz -C torch_dart
|
||||
rm torch_dart.tar.gz
|
||||
popd
|
||||
|
||||
- name: Fetch prebuilt reown_flutter
|
||||
run: |
|
||||
set -x -e
|
||||
pushd scripts
|
||||
rm -rf reown_flutter reown_flutter.tar.gz
|
||||
wget -q https://github.com/cake-tech/reown_flutter/releases/download/v0.0.4/reown_flutter-v0.0.4.tar.gz -O reown_flutter.tar.gz
|
||||
mkdir reown_flutter
|
||||
tar -xzf reown_flutter.tar.gz -C reown_flutter
|
||||
rm reown_flutter.tar.gz
|
||||
popd
|
||||
|
||||
- name: Clone BitBox Flutter
|
||||
run: |
|
||||
set -x -e
|
||||
pushd scripts
|
||||
./build_bitbox_flutter.sh
|
||||
popd
|
||||
|
||||
# ---- Native crypto cores (monero_c prebuilt bundle) ------------------
|
||||
- name: Fetch prebuilt monero_c bundle
|
||||
run: |
|
||||
set -x -e
|
||||
./scripts/prepare_moneroc.sh
|
||||
MONERO_C_TAG=$(cd scripts/monero_c && git describe --tags)
|
||||
mkdir -p "scripts/monero_c/release/$MONERO_C_TAG"
|
||||
pushd "scripts/monero_c/release/$MONERO_C_TAG"
|
||||
wget -q https://github.com/MrCyjaneK/monero_c/releases/download/v0.18.4.6-RC1/release-bundle.zip
|
||||
unzip -q release-bundle.zip
|
||||
rm release-bundle.zip
|
||||
echo "=== bundle contents (one level) ==="
|
||||
ls
|
||||
popd
|
||||
|
||||
# iOS native lib staging: Cake's scripts/ios/setup.sh + gen_framework.sh
|
||||
# expect pre-built .a archives in specific paths. The first run will
|
||||
# likely surface what's missing; we iterate from there.
|
||||
- name: Inspect iOS targets available in monero_c bundle
|
||||
run: |
|
||||
set -x
|
||||
MONERO_C_TAG=$(cd scripts/monero_c && git describe --tags)
|
||||
BUNDLE_DIR="scripts/monero_c/release/$MONERO_C_TAG"
|
||||
# List anything iOS-y
|
||||
find "$BUNDLE_DIR" -maxdepth 1 -name '*ios*' -o -name '*apple*' 2>/dev/null || true
|
||||
ls "$BUNDLE_DIR" || true
|
||||
|
||||
# ---- Configure: pubspec.yaml, Info.plist, GeneratedPluginRegistrant ---
|
||||
- name: Run iOS configure (cakewallet profile)
|
||||
run: |
|
||||
set -x -e
|
||||
pushd scripts/ios
|
||||
source ./app_env.sh cakewallet
|
||||
./app_config.sh
|
||||
popd
|
||||
|
||||
# ---- Secrets ---------------------------------------------------------
|
||||
- name: Generate per-module secrets.g.dart files (all empty defaults)
|
||||
run: dart run tool/generate_new_secrets.dart
|
||||
|
||||
- name: Inject Trocador affiliate secrets
|
||||
env:
|
||||
TROCADOR_API_KEY: ${{ secrets.TROCADOR_API_KEY }}
|
||||
TROCADOR_MONERO_API_KEY: ${{ secrets.TROCADOR_MONERO_API_KEY }}
|
||||
TROCADOR_EXCHANGE_MARKUP: ${{ secrets.TROCADOR_EXCHANGE_MARKUP }}
|
||||
run: |
|
||||
# macOS sed needs '' after -i; Linux sed doesn't accept that. This
|
||||
# workflow runs on macos only.
|
||||
sed -i '' \
|
||||
-e "s|const trocadorApiKey = '';|const trocadorApiKey = '${TROCADOR_API_KEY}';|" \
|
||||
-e "s|const trocadorMoneroApiKey = '';|const trocadorMoneroApiKey = '${TROCADOR_MONERO_API_KEY}';|" \
|
||||
-e "s|const trocadorExchangeMarkup = '';|const trocadorExchangeMarkup = '${TROCADOR_EXCHANGE_MARKUP:-1}';|" \
|
||||
lib/.secrets.g.dart
|
||||
grep '^const trocador' lib/.secrets.g.dart
|
||||
|
||||
# ---- Flutter init + codegen -----------------------------------------
|
||||
- name: Initialize Flutter SDK (iOS precache)
|
||||
run: |
|
||||
flutter --version
|
||||
flutter precache --ios --no-linux --no-android --no-macos --no-windows --no-fuchsia --no-web || true
|
||||
|
||||
- name: Build generated code (mobx + hive adapters)
|
||||
run: bash model_generator.sh
|
||||
|
||||
- name: Generate localization
|
||||
run: dart run tool/generate_localization.dart
|
||||
|
||||
# CocoaPods: the iOS Podfile installs Flutter plugin pods. Required
|
||||
# before flutter build can link them.
|
||||
- name: pod install
|
||||
run: |
|
||||
cd ios
|
||||
pod install --repo-update
|
||||
|
||||
# ---- Build iOS Simulator app (no codesign) ---------------------------
|
||||
- name: Build iOS Simulator app
|
||||
run: |
|
||||
set -x -e
|
||||
flutter build ios --simulator --no-codesign \
|
||||
--dart-define-from-file=env.json
|
||||
ls -la build/ios/iphonesimulator/
|
||||
|
||||
- name: Zip Runner.app
|
||||
run: |
|
||||
cd build/ios/iphonesimulator
|
||||
zip -r hash_wallet_ios_sim_${{ github.sha }}.zip Runner.app
|
||||
|
||||
- name: Upload .app artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: hash-wallet-ios-sim-${{ github.sha }}
|
||||
path: build/ios/iphonesimulator/hash_wallet_ios_sim_*.zip
|
||||
retention-days: 14
|
||||
266
.github/workflows/build-ios-testflight.yml
vendored
Normal file
266
.github/workflows/build-ios-testflight.yml
vendored
Normal file
@@ -0,0 +1,266 @@
|
||||
name: Hash Wallet iOS TestFlight build
|
||||
|
||||
# Phase 2 of iOS CI: full signed build that uploads to TestFlight.
|
||||
# Phase 1 (build-ios-sim.yml) validates the Mac runner with no signing —
|
||||
# run that first if TestFlight blows up unexpectedly.
|
||||
#
|
||||
# Required Gitea Actions secrets (all account/app credentials):
|
||||
# APPLE_TEAM_ID — 10-char (D8PL9F7X33)
|
||||
# APPLE_KEY_ID — 10-char (CHK6B69G58)
|
||||
# APPLE_ISSUER_ID — UUID
|
||||
# APPLE_API_KEY_P8_BASE64 — base64 of AuthKey_<KeyID>.p8
|
||||
# APPLE_DIST_CERT_P12_BASE64 — base64 of distribution.p12
|
||||
# APPLE_DIST_CERT_P12_PASSWORD — password set during openssl pkcs12 export
|
||||
# APPLE_PROVISIONING_PROFILE_BASE64 — base64 of Hash_Wallet.mobileprovision
|
||||
# APPLE_KEYCHAIN_PASSWORD — any string, used to create the temp keychain
|
||||
# TROCADOR_* — reused from Linux/Android
|
||||
|
||||
on:
|
||||
# Don't auto-trigger on every push — TestFlight uploads are slow and use
|
||||
# build numbers. Manual trigger only; later we can add a workflow_dispatch
|
||||
# input for build number or auto-bump.
|
||||
workflow_dispatch:
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: macos-latest
|
||||
env:
|
||||
APP_IOS_TYPE: cakewallet
|
||||
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Show toolchain
|
||||
run: |
|
||||
set -x
|
||||
flutter --version
|
||||
xcodebuild -version
|
||||
pod --version
|
||||
uname -m
|
||||
|
||||
# ---- External prebuilt deps -----------------------------------------
|
||||
- name: Fetch prebuilt torch_dart
|
||||
run: |
|
||||
set -x -e
|
||||
pushd scripts
|
||||
rm -rf torch_dart torch_dart.tar.gz
|
||||
wget -q https://github.com/MrCyjaneK/torch_dart/releases/download/v1.0.17/torch_dart-v1.0.17.tar.gz -O torch_dart.tar.gz
|
||||
mkdir torch_dart
|
||||
tar -xzf torch_dart.tar.gz -C torch_dart
|
||||
rm torch_dart.tar.gz
|
||||
popd
|
||||
|
||||
- name: Fetch prebuilt reown_flutter
|
||||
run: |
|
||||
set -x -e
|
||||
pushd scripts
|
||||
rm -rf reown_flutter reown_flutter.tar.gz
|
||||
wget -q https://github.com/cake-tech/reown_flutter/releases/download/v0.0.4/reown_flutter-v0.0.4.tar.gz -O reown_flutter.tar.gz
|
||||
mkdir reown_flutter
|
||||
tar -xzf reown_flutter.tar.gz -C reown_flutter
|
||||
rm reown_flutter.tar.gz
|
||||
popd
|
||||
|
||||
- name: Clone BitBox Flutter
|
||||
run: |
|
||||
set -x -e
|
||||
pushd scripts
|
||||
./build_bitbox_flutter.sh
|
||||
popd
|
||||
|
||||
- name: Fetch prebuilt monero_c bundle
|
||||
run: |
|
||||
set -x -e
|
||||
./scripts/prepare_moneroc.sh
|
||||
MONERO_C_TAG=$(cd scripts/monero_c && git describe --tags)
|
||||
mkdir -p "scripts/monero_c/release/$MONERO_C_TAG"
|
||||
pushd "scripts/monero_c/release/$MONERO_C_TAG"
|
||||
wget -q https://github.com/MrCyjaneK/monero_c/releases/download/v0.18.4.6-RC1/release-bundle.zip
|
||||
unzip -q release-bundle.zip
|
||||
rm release-bundle.zip
|
||||
popd
|
||||
|
||||
# ---- Configure: pubspec.yaml, Info.plist, etc. ----------------------
|
||||
- name: Run iOS configure (cakewallet profile)
|
||||
run: |
|
||||
set -x -e
|
||||
pushd scripts/ios
|
||||
source ./app_env.sh cakewallet
|
||||
./app_config.sh
|
||||
popd
|
||||
|
||||
# ---- Secrets ---------------------------------------------------------
|
||||
- name: Generate per-module secrets.g.dart files (empty defaults)
|
||||
run: dart run tool/generate_new_secrets.dart
|
||||
|
||||
- name: Inject Trocador affiliate secrets
|
||||
env:
|
||||
TROCADOR_API_KEY: ${{ secrets.TROCADOR_API_KEY }}
|
||||
TROCADOR_MONERO_API_KEY: ${{ secrets.TROCADOR_MONERO_API_KEY }}
|
||||
TROCADOR_EXCHANGE_MARKUP: ${{ secrets.TROCADOR_EXCHANGE_MARKUP }}
|
||||
run: |
|
||||
sed -i '' \
|
||||
-e "s|const trocadorApiKey = '';|const trocadorApiKey = '${TROCADOR_API_KEY}';|" \
|
||||
-e "s|const trocadorMoneroApiKey = '';|const trocadorMoneroApiKey = '${TROCADOR_MONERO_API_KEY}';|" \
|
||||
-e "s|const trocadorExchangeMarkup = '';|const trocadorExchangeMarkup = '${TROCADOR_EXCHANGE_MARKUP:-1}';|" \
|
||||
lib/.secrets.g.dart
|
||||
|
||||
# ---- Apple signing setup --------------------------------------------
|
||||
- name: Create temp keychain + import distribution cert
|
||||
env:
|
||||
APPLE_DIST_CERT_P12_BASE64: ${{ secrets.APPLE_DIST_CERT_P12_BASE64 }}
|
||||
APPLE_DIST_CERT_P12_PASSWORD: ${{ secrets.APPLE_DIST_CERT_P12_PASSWORD }}
|
||||
APPLE_KEYCHAIN_PASSWORD: ${{ secrets.APPLE_KEYCHAIN_PASSWORD }}
|
||||
run: |
|
||||
set -e
|
||||
KEYCHAIN_PATH="$RUNNER_TEMP/build.keychain-db"
|
||||
# Create + unlock dedicated keychain so we don't touch the user's login keychain
|
||||
security create-keychain -p "$APPLE_KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
|
||||
security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH" # 6 hours
|
||||
security unlock-keychain -p "$APPLE_KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
|
||||
# Add to user search list so codesign can find it
|
||||
security list-keychains -d user -s "$KEYCHAIN_PATH" $(security list-keychains -d user | sed 's/"//g')
|
||||
# Import the .p12
|
||||
P12="$RUNNER_TEMP/dist.p12"
|
||||
echo "$APPLE_DIST_CERT_P12_BASE64" | base64 -d > "$P12"
|
||||
security import "$P12" -k "$KEYCHAIN_PATH" -P "$APPLE_DIST_CERT_P12_PASSWORD" \
|
||||
-T /usr/bin/codesign -T /usr/bin/security
|
||||
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$APPLE_KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
|
||||
# Sanity-check: list identities the keychain offers
|
||||
security find-identity -v -p codesigning "$KEYCHAIN_PATH"
|
||||
rm -f "$P12"
|
||||
|
||||
- name: Install provisioning profile + parse name/UUID for ExportOptions
|
||||
env:
|
||||
APPLE_PROVISIONING_PROFILE_BASE64: ${{ secrets.APPLE_PROVISIONING_PROFILE_BASE64 }}
|
||||
run: |
|
||||
set -e
|
||||
PROFILES_DIR="$HOME/Library/MobileDevice/Provisioning Profiles"
|
||||
mkdir -p "$PROFILES_DIR"
|
||||
PROFILE="$RUNNER_TEMP/Hash_Wallet.mobileprovision"
|
||||
echo "$APPLE_PROVISIONING_PROFILE_BASE64" | base64 -d > "$PROFILE"
|
||||
|
||||
# Parse the .mobileprovision to get its UUID + Name (CMS-decoded plist).
|
||||
PROFILE_UUID=$(security cms -D -i "$PROFILE" | plutil -extract UUID raw -o - -)
|
||||
PROFILE_NAME=$(security cms -D -i "$PROFILE" | plutil -extract Name raw -o - -)
|
||||
echo "Profile UUID: $PROFILE_UUID"
|
||||
echo "Profile name: $PROFILE_NAME"
|
||||
echo "PROFILE_UUID=$PROFILE_UUID" >> "$GITHUB_ENV"
|
||||
echo "PROFILE_NAME=$PROFILE_NAME" >> "$GITHUB_ENV"
|
||||
|
||||
# Xcode looks profiles up by UUID filename.
|
||||
cp "$PROFILE" "$PROFILES_DIR/$PROFILE_UUID.mobileprovision"
|
||||
ls -la "$PROFILES_DIR" | head -10
|
||||
|
||||
- name: Install App Store Connect API key for altool
|
||||
env:
|
||||
APPLE_API_KEY_P8_BASE64: ${{ secrets.APPLE_API_KEY_P8_BASE64 }}
|
||||
APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }}
|
||||
run: |
|
||||
set -e
|
||||
mkdir -p "$HOME/.appstoreconnect/private_keys"
|
||||
echo "$APPLE_API_KEY_P8_BASE64" | base64 -d > "$HOME/.appstoreconnect/private_keys/AuthKey_${APPLE_KEY_ID}.p8"
|
||||
ls -la "$HOME/.appstoreconnect/private_keys/"
|
||||
|
||||
# ---- Flutter init + codegen + pod install ---------------------------
|
||||
- name: Initialize Flutter SDK (iOS precache)
|
||||
run: |
|
||||
flutter --version
|
||||
flutter precache --ios --no-linux --no-android --no-macos --no-windows --no-fuchsia --no-web || true
|
||||
|
||||
- name: Build generated code
|
||||
run: bash model_generator.sh
|
||||
|
||||
- name: Generate localization
|
||||
run: dart run tool/generate_localization.dart
|
||||
|
||||
- name: pod install
|
||||
run: |
|
||||
cd ios
|
||||
pod install --repo-update
|
||||
|
||||
# ---- Generate ExportOptions.plist + build IPA -----------------------
|
||||
- name: Write ExportOptions.plist
|
||||
env:
|
||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||
run: |
|
||||
cat > ios/ExportOptions.plist <<EOF
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>method</key>
|
||||
<string>app-store</string>
|
||||
<key>teamID</key>
|
||||
<string>${APPLE_TEAM_ID}</string>
|
||||
<key>signingStyle</key>
|
||||
<string>manual</string>
|
||||
<key>signingCertificate</key>
|
||||
<string>Apple Distribution</string>
|
||||
<key>provisioningProfiles</key>
|
||||
<dict>
|
||||
<key>com.suchsoftware.hashwallet</key>
|
||||
<string>${PROFILE_NAME}</string>
|
||||
</dict>
|
||||
<key>uploadBitcode</key>
|
||||
<false/>
|
||||
<key>uploadSymbols</key>
|
||||
<true/>
|
||||
<key>destination</key>
|
||||
<string>export</string>
|
||||
<key>stripSwiftSymbols</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
EOF
|
||||
cat ios/ExportOptions.plist
|
||||
|
||||
- name: Build IPA
|
||||
run: |
|
||||
set -x -e
|
||||
flutter build ipa --release \
|
||||
--dart-define-from-file=env.json \
|
||||
--export-options-plist=ios/ExportOptions.plist
|
||||
ls -la build/ios/ipa/
|
||||
|
||||
- name: Upload IPA artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: hash-wallet-ios-${{ github.sha }}
|
||||
path: build/ios/ipa/*.ipa
|
||||
retention-days: 30
|
||||
|
||||
# ---- Upload to TestFlight -------------------------------------------
|
||||
- name: Upload to TestFlight via altool
|
||||
env:
|
||||
APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }}
|
||||
APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }}
|
||||
run: |
|
||||
set -e
|
||||
IPA=$(ls build/ios/ipa/*.ipa | head -1)
|
||||
echo "Uploading $IPA to TestFlight..."
|
||||
xcrun altool --upload-app \
|
||||
--type ios \
|
||||
--file "$IPA" \
|
||||
--apiKey "$APPLE_KEY_ID" \
|
||||
--apiIssuer "$APPLE_ISSUER_ID"
|
||||
|
||||
# ---- Cleanup keychain so we don't leak it across builds -------------
|
||||
- name: Cleanup
|
||||
if: always()
|
||||
env:
|
||||
APPLE_KEYCHAIN_PASSWORD: ${{ secrets.APPLE_KEYCHAIN_PASSWORD }}
|
||||
run: |
|
||||
set +e
|
||||
KEYCHAIN_PATH="$RUNNER_TEMP/build.keychain-db"
|
||||
security delete-keychain "$KEYCHAIN_PATH" 2>/dev/null
|
||||
rm -rf "$HOME/.appstoreconnect/private_keys"
|
||||
rm -f "$HOME/Library/MobileDevice/Provisioning Profiles"/*.mobileprovision
|
||||
true
|
||||
@@ -45,7 +45,11 @@ class TopBar extends StatelessWidget {
|
||||
isSyncHeavy: dashboardViewModel.isSyncHeavy,
|
||||
),
|
||||
ModernButton.svg(
|
||||
iconColor: Theme.of(context).colorScheme.primary,
|
||||
// Hash Wallet: was theme.colorScheme.primary (dark forest green)
|
||||
// which rendered the gear icon nearly invisible on the dark
|
||||
// dashboard backdrop. onSurfaceVariant is the de-emphasized-
|
||||
// foreground Material token.
|
||||
iconColor: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
size: 36,
|
||||
onPressed: () {
|
||||
HapticFeedback.mediumImpact();
|
||||
|
||||
@@ -122,7 +122,11 @@ class _NEWNewMainNavBarState extends State<NewMainNavBar> {
|
||||
final backgroundColor = theme.colorScheme.surfaceContainer.withAlpha(127);
|
||||
final pillColor = theme.colorScheme.onSurface.withAlpha(25);
|
||||
final activeColor = theme.colorScheme.onSurface;
|
||||
final inactiveColor = theme.colorScheme.primary;
|
||||
// Hash Wallet: was theme.colorScheme.primary — that's our brand forest
|
||||
// green (#1A5C38), which renders dark-on-dark against the navbar's
|
||||
// semi-transparent surface backdrop. Material's onSurfaceVariant is the
|
||||
// standard token for de-emphasized icons and is visible across themes.
|
||||
final inactiveColor = theme.colorScheme.onSurfaceVariant;
|
||||
|
||||
return Observer(
|
||||
builder: (_) {
|
||||
|
||||
@@ -66,13 +66,15 @@ class SeedVerificationSuccessView extends StatelessWidget {
|
||||
PrimaryButton(
|
||||
key: ValueKey('wallet_seed_page_open_wallet_button_key'),
|
||||
onPressed: () {
|
||||
if (walletType == WalletType.bitcoin) {
|
||||
Navigator.of(context).pushNamed(Routes.lightningUsernamePage, arguments: true);
|
||||
} else {
|
||||
Navigator.of(context).popUntil((route) => route.isFirst);
|
||||
}
|
||||
// Hash Wallet: Lightning Username onboarding skipped. The original
|
||||
// Cake flow pushed BTC wallets to the lightning_username_page,
|
||||
// which suggests an @cake.cash address. We disabled Lightning
|
||||
// entirely (no Greenlight infra) and the screen is meaningless
|
||||
// without it. Re-enable here if we ever stand up our own LN
|
||||
// backend + domain.
|
||||
Navigator.of(context).popUntil((route) => route.isFirst);
|
||||
},
|
||||
text: (walletType == WalletType.bitcoin) ? S.current.continue_text : S.current.open_wallet,
|
||||
text: S.current.open_wallet,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
textColor: Theme.of(context).colorScheme.onPrimary,
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user