Overview
Libwallet uses gomobile to create mobile-compatible bindings from Go code. This allows the same core wallet logic to be shared across Android and iOS applications.Gomobile generates platform-specific libraries (
.aar for Android, .framework for iOS) that can be imported directly into mobile projects.How Gomobile Works
Gomobile binds Go packages to mobile platforms by:- Code Generation: Creates platform-specific wrapper code
- Type Mapping: Converts Go types to Java/Kotlin (Android) or Objective-C/Swift (iOS)
- Library Packaging: Produces native library artifacts (AAR/framework)
Type Limitations
Gomobile has restrictions on exportable types:- No Go slices (use custom wrapper types)
- No maps (use custom collections)
- Limited struct field visibility
- No variadic functions
StringList and IntList (bridge.go:11-81):
These wrapper types provide a mobile-friendly API while internally using native Go data structures.
Build Process
Android Build
The Android build process is automated throughtools/libwallet-android.sh:
1. Bootstrap Gomobile
First, the build script ensures gomobile is installed (tools/bootstrap-gomobile.sh:12-14):
The script uses a shared
GOMODCACHE to cache dependencies and speed up subsequent builds.2. Prepare Build Environment
The script creates necessary cache directories (tools/libwallet-android.sh:18-22):
3. Clean Temporary Files
Gomobile can create conflicting temporary directories, so these are cleaned before each build (tools/libwallet-android.sh:31-32):
4. Configure Page Size Alignment
For Android targetSdk 35+, 16KB page alignment is required (tools/libwallet-android.sh:50):
Android 15 (API 35+) introduces 16KB page size support. These linker flags ensure the compiled library is compatible with devices using larger page sizes.
-Wl,-z,max-page-size=16384: Sets maximum page size to 16KB-Wl,-z,common-page-size=16384: Aligns data sections to 16KB boundaries- Both
CGO_LDFLAGSandLDFLAGSare set for compatibility across build scenarios
5. Run Gomobile Bind
Finally, the script generates the Android AAR (tools/libwallet-android.sh:56-60):
-target="android": Generate Android bindings-androidapi 19: Minimum API level (Android 4.4)-trimpath: Remove absolute paths for reproducible builds-ldflags="-buildid=. -v": Consistent build IDs for reproducibility- Multiple packages:
libwallet,newop,app_provided_data,libwallet_init
The build binds multiple packages to provide different functional areas to the mobile app.
Build Output
The Android build produceslibwallet.aar at:
- Compiled native libraries for all Android architectures (arm, arm64, x86, x86_64)
- Java/Kotlin binding classes
- Metadata and manifest files
Reproducible Builds
Muun prioritizes reproducible builds for security and transparency:Key Techniques
- Trimmed Paths:
-trimpathremoves machine-specific absolute paths - Consistent Build IDs:
-ldflags="-buildid=."ensures identical builds - Vendor Dependencies: Using
go build -mod=vendorlocks dependencies - Cache Management: Shared build caches prevent inconsistencies
Reproducible builds allow independent verification that published binaries match the source code.
Integration with Mobile Apps
Android Integration
- Add the AAR to your Android project:
- Import and use libwallet classes:
iOS Integration
For iOS, gomobile generates a.framework bundle:
Build Caching
The build scripts use strategic caching to improve performance:Caching can reduce rebuild times from minutes to seconds when only Go code changes.
Cross-Platform Packages
Libwallet binds multiple packages for different concerns:Core Package (libwallet)
Main wallet functionality:
- Transaction building and signing
- Key management
- Address generation
- Submarine swaps
NewOp Package (newop)
New operation handling:
- Fee calculation
- Exchange rates
- Payment state management
App-Provided Data (app_provided_data)
Platform-specific configuration:
- Network settings
- Storage paths
- Platform capabilities
Initialization (libwallet_init)
Library initialization and configuration.
Debugging Build Issues
Common Problems
Build fails with “file exists” error:Always ensure Rust libraries are built before attempting to build libwallet with gomobile.
Performance Considerations
Build Time Optimization
- Use build caches (
GOCACHE,GOMODCACHE) - Parallelize independent builds
- Only rebuild when necessary
Runtime Performance
Gomobile adds some overhead:- Cross-language calls have marshaling cost
- Batch operations when possible
- Keep complex logic in Go layer
- Use native types internally, bridge types only at boundaries
Version Management
Gomobile version is pinned ingo.mod:
Next Steps
Libwallet Overview
Learn about libwallet’s core functionality
Gomobile Docs
Official gomobile documentation