Native macOS application demonstrating the Stellar SDK with SwiftUI and complete integration with all 11 SDK feature demonstrations.
This is a native macOS app built with SwiftUI (not Compose), showcasing the full Stellar SDK feature set:
- Key Generation: Generate and manage Stellar keypairs
- Account Management: Fund testnet accounts and fetch account details
- Payments: Send XLM and custom assets
- Trustlines: Establish trust to hold issued assets
- Transaction Details: View transaction operations and events
- Smart Contracts: Fetch and parse Soroban contract details
- Contract Deployment: Upload and deploy WASM contracts to testnet
- Contract Invocation: Invoke hello world, auth, and token contracts with full authorization
The app also includes an Info screen with app version, GitHub repository link, and contact information. The Info screen is not an SDK feature demonstration - it provides app metadata and support information.
The app demonstrates how to integrate the Kotlin Multiplatform Stellar SDK into a pure SwiftUI macOS application.
┌──────────────────────────────────────────────┐
│ demo:shared (Kotlin Framework) │
│ • Stellar SDK business logic │
│ • Exported from KMP shared module │
│ • No Compose UI (macOS-specific) │
└──────────────────────────────────────────────┘
▼
┌──────────────────────────────────────────────┐
│ demo:macosApp (30 Swift files) │
│ • Native SwiftUI UI (Material 3 design) │
│ • 13 Views (one per feature screen) │
│ • 10 Components (reusable UI) │
│ • 6 Utilities (helpers) │
└──────────────────────────────────────────────┘
Short answer: Compose Multiplatform's native macOS support is limited. The Desktop (JVM) version is recommended for Compose UI on macOS.
Two options for macOS:
| Feature | Desktop App (JVM) | macOS Native App |
|---|---|---|
| UI Framework | Compose Multiplatform | SwiftUI |
| Code Sharing | 100% shared UI | Business logic only |
| Bundle Size | ~35 MB (includes JVM) | ~8 MB (native) |
| Performance | Good | Excellent |
| Platform APIs | Limited | Full AppKit access |
| Cross-platform | macOS/Windows/Linux | macOS only |
| Recommendation | ✅ For Compose UI | For native experience |
The macOS app was recently refactored from a single file to a well-structured project:
Before: 1 monolithic Swift file After: 30 organized Swift files:
- 13 Views: Dedicated view for each feature screen
- 10 Components: Reusable UI components
- 6 Utilities: Helper classes
- 1 App: Main entry point
macosApp/
├── StellarDemo/
│ ├── StellarDemoApp.swift # App entry point
│ ├── Views/ # 13 SwiftUI views
│ │ ├── MainScreen.swift
│ │ ├── KeyGenerationView.swift
│ │ ├── FundAccountView.swift
│ │ ├── AccountDetailsView.swift
│ │ ├── TrustAssetView.swift
│ │ ├── SendPaymentView.swift
│ │ ├── FetchTransactionView.swift
│ │ ├── ContractDetailsView.swift
│ │ ├── DeployContractView.swift
│ │ ├── InvokeHelloWorldContractScreen.swift
│ │ ├── InvokeAuthContractScreen.swift
│ │ ├── InvokeTokenContractScreen.swift
│ │ └── InfoView.swift
│ ├── Components/ # 10 reusable components
│ │ ├── DemoTopicCard.swift
│ │ ├── InfoCard.swift
│ │ ├── LoadingButton.swift
│ │ ├── NavigationToolbar.swift
│ │ ├── StellarTextField.swift
│ │ ├── KeyPairComponents.swift
│ │ ├── AccountComponents.swift
│ │ ├── TrustAssetComponents.swift
│ │ ├── PaymentComponents.swift
│ │ └── ContractComponents.swift
│ └── Utilities/ # 6 utility classes
│ ├── Material3Colors.swift
│ ├── MacOSBridgeWrapper.swift
│ ├── ToastManager.swift
│ ├── KeyPairExtension.swift
│ ├── FormValidation.swift
│ └── ClipboardHelper.swift
├── project.yml # xcodegen configuration
├── build.gradle.kts # Gradle helper tasks
├── StellarDemo.xcodeproj/ # Generated (gitignored)
└── README.md # This file
- macOS: 13.0 (Ventura) or newer
- Xcode: 15.0 or newer
- xcodegen: Project generator
brew install xcodegen
- libsodium: Required by Stellar SDK
brew install libsodium
- Deployment Target: macOS 13.0 or higher (demo app requirement; SDK itself supports macOS 11.0+)
- Swift: 5.9+
- Kotlin: 2.0+ (for building the framework)
# Install xcodegen (project generator)
brew install xcodegen
# Install libsodium (required by Stellar SDK)
brew install libsodium
# Verify installations
xcodegen --version
brew list libsodiumFrom project root:
# For Apple Silicon (M1/M2/M3)
./gradlew :demo:shared:linkDebugFrameworkMacosArm64
# For Intel Macs
./gradlew :demo:shared:linkDebugFrameworkMacosX64Or use the Gradle helper task:
./gradlew :demo:macosApp:buildFrameworkThis automatically detects your architecture and builds the correct framework.
cd demo/macosApp
xcodegen generateThis creates StellarDemo.xcodeproj from project.yml.
open StellarDemo.xcodeprojOr use the all-in-one Gradle task (from project root):
./gradlew :demo:macosApp:openXcodeThis builds the framework, generates the project, and opens Xcode.
In Xcode:
- Select scheme: "StellarDemo" (should be selected by default)
- Select destination: "My Mac"
- Run: Click the Play button (▶) or press ⌘R
All 11 SDK feature demonstrations are fully implemented in SwiftUI:
- View:
KeyGenerationView.swift - Component:
KeyPairComponents.swift - Generate random Stellar keypairs
- Display account ID (G...) and secret seed (S...)
- Copy to clipboard (macOS pasteboard)
- Sign and verify test data
- Uses:
KeyPair.random()from Stellar SDK
- View:
FundAccountView.swift - Request XLM from Friendbot
- Real-time funding status with toast notifications
- Error handling for invalid accounts
- Uses:
FriendBot.fundTestnetAccount()from Stellar SDK
- View:
AccountDetailsView.swift - Component:
AccountComponents.swift - Retrieve account information from Horizon
- Display all balances (XLM and issued assets)
- Show sequence number and flags
- Uses:
Server.accounts()from Stellar SDK
- View:
TrustAssetView.swift - Component:
TrustAssetComponents.swift - Establish trustlines for issued assets
- Support for custom asset codes and issuers
- Build, sign, and submit transactions
- Uses:
ChangeTrustOperationfrom Stellar SDK
- View:
SendPaymentView.swift - Component:
PaymentComponents.swift - Transfer XLM or issued assets
- Support for native and custom assets
- Amount validation and transaction signing
- Uses:
PaymentOperationfrom Stellar SDK
- View:
FetchTransactionView.swift - Fetch and display transaction details from Horizon or Soroban RPC
- View operations, events, and smart contract data
- Expandable sections with copy functionality
- Human-readable SCVal formatting
- Uses:
HorizonServer.transactions(),SorobanServer.getTransaction()
- View:
ContractDetailsView.swift - Component:
ContractComponents.swift - Parse WASM contracts to view metadata
- Display contract specification (functions, types)
- View contract code hash
- Uses: Soroban RPC integration from Stellar SDK
- View:
DeployContractView.swift - Upload and deploy WASM contracts
- Platform-specific resource loading from bundle
- One-step and two-step deployment
- Uses:
ContractClient.deploy(),install(),deployFromWasmId()
- View:
InvokeHelloWorldContractView.swift - Invoke deployed "Hello World" contract
- Map-based argument conversion
- Automatic type handling
- Uses:
ContractClient.invoke(),funcArgsToXdrSCValues(),funcResToNative()
- View:
InvokeAuthContractView.swift - Dynamic authorization handling
- Same-invoker vs different-invoker scenarios
- Conditional signing with
needsNonInvokerSigningBy() - Uses:
ContractClient.buildInvoke(),signAuthEntries(),funcResToNative()
- View:
InvokeTokenContractView.swift - SEP-41 token contract interaction
- Advanced multi-signature workflows with
buildInvoke() - Function selection from contract spec
- Automatic type conversion for token operations
- Uses:
ContractClient.buildInvoke(), token interface support
The app includes an Info screen that provides app information (not an SDK feature demonstration):
- View:
InfoView.swift - Display app version (from demo.version in gradle.properties)
- About the KMP Stellar SDK
- GitHub repository link (opens in default browser)
- Support message
- Feedback email (opens in default email client)
The app uses a Material 3-inspired color scheme adapted for macOS:
// Primary colors matching Material 3
static let primary = Color(red: 0.38, green: 0.49, blue: 0.54)
static let onPrimary = Color.white
static let primaryContainer = Color(red: 0.78, green: 0.85, blue: 0.88)
static let onPrimaryContainer = Color(red: 0.05, green: 0.17, blue: 0.21)
// Surface colors
static let surface = Color(NSColor.controlBackgroundColor)
static let onSurface = Color(NSColor.labelColor)This provides:
- Consistent design across demo apps
- Proper dark mode support
- Native macOS integration
- Accessible color contrasts
DemoTopicCard: Card component for main menu
DemoTopicCard(
title: "Key Generation",
description: "Generate and manage Stellar keypairs",
icon: "key.fill"
) {
// Navigation action
}ToastManager: macOS-native toast notifications
ToastManager.shared.show(message: "Account funded successfully!", isError: false)KeyPairExtension: Helper methods for KeyPair
extension KeyPair {
func formattedAccountId() -> String
func formattedSecretSeed() -> String
}- SwiftUI: Declarative UI framework
- AppKit: Native macOS frameworks
- Combine: Reactive programming (for async calls)
- Foundation: Core utilities
- Stellar SDK: All Stellar functionality
- Ktor Client: HTTP networking
- kotlinx.serialization: JSON parsing
- kotlinx.coroutines: Async operations
- libsodium: Ed25519 cryptography (via Homebrew)
- Installed system-wide:
/opt/homebrew/opt/libsodium/ - Linked in Xcode project settings
- Installed system-wide:
bundleIdPrefix: com.soneso.demo
# Full ID: com.soneso.demo.StellarDemoMARKETING_VERSION: "1.0" # User-facing version
CURRENT_PROJECT_VERSION: "1" # Build numberdeploymentTarget:
macOS: 13.0The Xcode project is configured to find the Kotlin framework:
FRAMEWORK_SEARCH_PATHS:
- $(SRCROOT)/../../shared/build/bin/macosArm64/debugFramework
- $(SRCROOT)/../../shared/build/bin/macosX64/debugFrameworkLIBRARY_SEARCH_PATHS:
- /opt/homebrew/opt/libsodium/lib
HEADER_SEARCH_PATHS:
- /opt/homebrew/opt/libsodium/include
OTHER_LDFLAGS:
- -lsodiumThe app connects to Stellar testnet:
- Horizon:
https://horizon-testnet.stellar.org - Soroban RPC:
https://soroban-testnet.stellar.org
To change networks, modify the SDK initialization in the Kotlin framework.
- Build: ⌘B
- Run: ⌘R
- Test all features: Navigate through all 11 SDK feature demonstration screens
Test all 11 SDK feature demonstrations:
- Key Generation: Generate keypair, copy to clipboard
- Fund Account: Fund a testnet account
- Account Details: Fetch and display account info
- Trust Asset: Establish a trustline
- Send Payment: Send XLM to another account
- Fetch Transaction Details: View transaction operations and events
- Contract Details: Fetch contract metadata
- Deploy Contract: Upload and deploy WASM contract
- Invoke Hello World: Invoke hello world contract
- Invoke Auth: Test authorization scenarios
- Invoke Token: Interact with token contract
Test with different network conditions:
- Normal network
- Slow network (Network Link Conditioner)
- No network (verify error handling)
View logs in Xcode's console:
- Show console: View → Debug Area → Activate Console (⌘⇧Y)
- Filter logs: Type in filter box
Add print statements in Swift:
print("Debug: \(variableName)")In Kotlin (shared framework):
println("Debug: $variableName")Set breakpoints in Swift code:
- Click line number to add breakpoint
- Run with debugger (⌘R)
- Inspect variables in Debug Navigator
Note: Cannot debug Kotlin code from Xcode. Use print statements.
Useful LLDB commands in console:
po variableName # Print object
frame variable # Show all variables
bt # Backtrace
continue # Continue execution
Framework not found:
# Rebuild the framework (from project root)
./gradlew :demo:shared:linkDebugFrameworkMacosArm64
# Regenerate Xcode project
cd demo/macosApp
xcodegen generatelibsodium not found:
# Install libsodium
brew install libsodium
# Verify installation
brew list libsodium
# Check library exists
ls /opt/homebrew/opt/libsodium/lib/libsodium.dylibArchitecture mismatch:
# Check your Mac's architecture
uname -m
# arm64 = Apple Silicon
# x86_64 = Intel
# Build for Apple Silicon
./gradlew :demo:shared:linkDebugFrameworkMacosArm64
# Build for Intel
./gradlew :demo:shared:linkDebugFrameworkMacosX64"No such module 'shared'":
- Clean build folder: Product → Clean Build Folder (⇧⌘K)
- Build framework first:
./gradlew :demo:shared:linkDebugFrameworkMacosArm64 - Check Framework Search Paths in Build Settings
Code signing error:
- Signing & Capabilities → Select your team
- Or disable signing for development: Build Settings → Code Signing → Sign to Run Locally
xcodegen not found:
brew install xcodegen
# Add to PATH if needed
echo 'export PATH="/opt/homebrew/bin:$PATH"' >> ~/.zshrcApp crashes on launch:
- Check Xcode console for stack traces
- Verify macOS version is 13.0+
- Ensure libsodium is installed
SwiftUI previews fail:
- SwiftUI previews don't work with KMP frameworks
- Use the full app for testing instead
- Or comment out framework imports for preview-only code
Network errors:
- Check internet connection
- Verify Horizon/Soroban URLs are correct
- Check macOS firewall settings
Toast notifications not showing:
- Toast uses NSUserNotification (legacy) or modern APIs
- Check notification permissions in System Settings
- Debug: ~8 MB
- Release (optimized): ~5 MB
Much smaller than JVM Desktop app (~35 MB).
- First build: 2-3 minutes (including framework)
- Incremental build: 10-30 seconds
- Framework only: 30-60 seconds
- Startup time: <1 second (native app)
- Frame rate: 60-120 FPS (ProMotion displays)
- Memory usage: 40-80 MB
- Select scheme: StellarDemo
- Select destination: Any Mac
- Archive: Product → Archive
- Organizer: Window → Organizer
- Select archive: Choose latest
- Distribute: Direct Distribution
- Options:
- Developer ID signed
- Include symbols
- Notarize app
- Export: Save .app or .pkg
# Upload for notarization
xcrun notarytool submit StellarDemo.zip \
--apple-id "your@email.com" \
--team-id "TEAMID" \
--password "app-specific-password"
# Check status
xcrun notarytool info <submission-id> \
--apple-id "your@email.com" \
--team-id "TEAMID" \
--password "app-specific-password"
# Staple ticket to app
xcrun stapler staple StellarDemo.app- Enroll in Apple Developer Program ($99/year)
- Create app in App Store Connect
- Archive and upload from Xcode
- Fill metadata: Screenshots, description
- Submit for review
- Sign with Developer ID: For distribution outside Mac App Store
- Notarize: Required for macOS 10.15+
- Distribute: .dmg, .pkg, or .zip
- Build release: Archive and export
- Create .dmg: Use create-dmg or similar tool
- Upload to GitHub: Attach to release
- Provide installation instructions
The JVM desktopApp module:
- ✅ Uses Compose UI (100% shared with Android/iOS/Web)
- ✅ Cross-platform (macOS/Windows/Linux)
- ✅ Hot reload in development
- ❌ Requires JVM (larger bundle: ~35 MB)
- ❌ Slower startup time
This macosApp module:
- ✅ True native macOS app
- ✅ Smaller bundle size (~8 MB)
- ✅ Faster startup time
- ✅ Full AppKit/SwiftUI access
- ✅ Better macOS integration
- ❌ SwiftUI UI (not shared with other platforms)
- ❌ macOS-only (not cross-platform)
Use Desktop App if you want:
- Compose UI shared with other platforms
- Cross-platform support (macOS/Windows/Linux)
- Faster development (less platform-specific code)
Use macOS Native App if you want:
- True native macOS experience
- Smaller bundle size
- Best performance
- Full macOS platform API access
- And you're willing to maintain SwiftUI code separately
This project uses xcodegen to generate the Xcode project from project.yml.
- Version control friendly:
.xcodeprojis gitignored - No merge conflicts: Project is generated, not edited
- Declarative: Simple YAML instead of complex XML
- Reproducible: Same project every time
cd demo/macosApp
xcodegen generateRun this whenever you:
- Pull changes from git
- Modify
project.yml - Add/remove Swift files
- Change build settings
- Main Demo README
- Shared Module
- SDK Documentation
- Desktop App README - Compare with JVM version
For issues:
- macOS-specific: Check this README and Xcode console
- Framework build: Check Gradle output
- SDK functionality: See main SDK documentation
- Stellar protocol: Visit developers.stellar.org
Part of the Stellar KMP SDK project. See main repository for license details.