iOS crypto wallet prototype built for the TON Wallet Contest.
Awarded 3rd place with a $3,000 prize.
TON Wallet iOS Contest is an older contest project focused on the core mobile wallet experience for The Open Network:
- Wallet onboarding and recovery phrase flows
- Passcode and biometric lock flows
- Main wallet balance screen
- Receive flow with QR-code generation
- Send and transfer flows
- Transaction history and transaction details
- TON deep-link handling through the
ton://URL scheme - Wallet settings for currency, contract version, Face ID, and notifications
This repository is intentionally preserved as a contest-era UIKit project. The current cleanup focuses on making it easier to inspect, build, and discuss as a portfolio artifact without rewriting the product or changing the original visual identity.
- 3rd place
- $3,000 award
- Built as an independent contest project
- UIKit-first wallet UI with custom controls, collection views, table views, animations, and QR-code rendering
- VIPER-like screen structure using
ViewController,Presenter,Router, andConfiguratorfiles per flow - Local framework split for UI components, entities, utilities, QR code generation, and signal primitives
- TON wallet integration through SwiftyTON, including wallet creation, wallet import, contract versions, balance loading, and transfer message creation
- Security-sensitive UX surfaces: recovery phrase, passcode setup, biometric lock, wallet unlock, and transaction confirmation
- Network-aware wallet refresh and currency conversion via CoinGecko
- Deep-link routing for TON transfer links
The project is organized as an Xcode workspace with a main app target and several local framework projects:
TONApp- main iOS app, screen assembly, navigation, services, TON wallet orchestration, persistence, and app lifecycleWalletUI- reusable UIKit components, controls, cells, labels, QR rendering helpers, and theme primitivesWalletEntity- entities and constants used across wallet screensWalletUtils- UIKit and Foundation helper extensionsQrCode- QR-code generation wrapper built onWalletUIandSwiftSignalKitSwiftSignalKit- vendored signal primitives used by QR-code renderingWalletCoreandWalletUrl- early local modules kept for project history; they are not currently part of the main workspace
Most app flows follow this structure:
ViewControllerowns UIKit layout, view state, and user events.Presenterowns presentation logic and service calls.Routerowns navigation.Configuratorwires dependencies.
Important logic lives in:
TONApp/TONApp/Service/TON/WalletManager.swiftTONApp/TONApp/Service/TON/KeystoreManager.swiftTONApp/TONApp/Persistence/DatabaseManager.swiftTONApp/TONApp/Service/ExchangeManager.swiftTONApp/TONApp/Service/ProcessTransactionsManager.swift
Recent cleanup tightened several high-risk boundaries without changing the app concept:
- Wallet contract selection is centralized in
WalletManagerinstead of being force-cast in presenters. - Main wallet loading and network monitoring use cancellable tasks with weak captures.
- QR scanning starts and stops
AVCaptureSessionon a serial camera queue and ignores duplicate QR detections. - Exchange-rate networking now has deterministic completion behavior and local error types.
- Recent transaction persistence uses a property-list-safe representation instead of Swift tuples.
- Key and wallet file writes are atomic and use iOS file protection options.
Current screenshot placeholders:
Recommended portfolio follow-up: replace these placeholders with fresh simulator screenshots or a short GIF covering onboarding, wallet balance, receive QR, and transaction details.
- Xcode with iOS Simulator support
- iOS 14.0 or later deployment target
- Swift 5 project settings
- Swift Package Manager
The project was originally created with Xcode 14.x-era settings. It has been inspected with Xcode 26.5, but current build verification is blocked by an upstream binary dependency issue described below.
- Open
TONApp.xcworkspace. - Select the
TONAppscheme. - Resolve Swift packages.
- Build and run on an iPhone simulator.
Command-line build shape:
DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer \
xcodebuild \
-workspace TONApp.xcworkspace \
-scheme TONApp \
-destination 'platform=iOS Simulator,name=iPhone 16,OS=18.5' \
buildThe original labraburn/SwiftyTON repository is no longer available on GitHub. The workspace now points to a public fork that still contains the exact commit pinned by the original Package.resolved file:
351296979a68f292c03c0adf952389d0f25f69b0
Package resolution now reaches SwiftyTON, but SwiftyTON itself depends on deleted binary release assets from labraburn/tonlib-xcframework:
TON.xcframework.zipOpenSSL.xcframework.zip
To fully restore builds, those binary artifacts need to be restored, mirrored, or replaced with a maintained TON Swift integration. That work is intentionally not done here because it would be a dependency recovery task, not a small portfolio cleanup.
- Recovery words and the app passcode are still stored through
UserDefaults, matching the contest-era implementation. A production wallet should move these flows to a Keychain-backed model with a migration plan. - SwiftyTON is configured with a hardcoded local SDK password from the original implementation. Replacing it safely would require wallet data migration and compatibility testing.
SwiftSignalKit, QR rendering helpers, and historicalWalletCoresources still contain older Swift patterns. They are preserved as local/vendor code rather than broadly modernized.- Automated test coverage is still minimal; the current cleanup focused on static safety, lifecycle, and presentation quality.
This project was built under contest constraints. If I were rebuilding it today, I would improve:
- Replace the unavailable TON binary dependency with a maintained, reproducible integration
- Move dependency setup to a single documented package strategy
- Tighten architecture boundaries between UI, wallet domain logic, persistence, and networking
- Move recovery phrase and passcode persistence to Keychain-backed storage with migration support
- Replace the hardcoded TON SDK local password with a secure, user/device-bound secret strategy
- Add unit tests for wallet state, transaction grouping, amount validation, and settings behavior
- Add UI tests for onboarding, unlock, receive, send, and deep-link flows
- Expand accessibility labels, traits, Dynamic Type behavior, and VoiceOver validation
- Improve error presentation for wallet creation, import, transfer creation, camera access, and network failures
- Adopt modern Swift concurrency consistently where it clarifies data flow
- Add fresh screenshots and a short demo GIF
Built by Ivan Nichypar.
Senior iOS Engineer focused on SwiftUI, UIKit, complex UI systems, accessibility, performance, framework-level debugging, and product-quality mobile UX.