> Comprehensive knowledge base for AI coding agents (Claude Code, Gemini CLI, Codex, OpenCode) working on the SwiftWarplyFramework iOS SDK.
---
## 1. Project Overview
**SwiftWarplyFramework** is a native iOS loyalty/rewards SDK (version 2.3.0) built in Swift for the DEI (Public Power Corporation of Greece) engagement platform. It provides a complete loyalty program toolkit including campaigns, coupons, merchant discovery, user profiles, card management, transaction history, and market pass (supermarket deals) features.
| **Singleton** | `WarplySDK.shared`, `NetworkService.shared`, `DatabaseManager.shared`, `EventDispatcher.shared` | Main entry points for all subsystems |
| **Enum-based Routing** | `Endpoint` enum | All API endpoints defined as enum cases with computed properties for path, method, parameters, auth type |
| **Dual API Surface** | All public SDK methods | Every API has both callback-based and `async/await` variants |
| **Event Bus (Dual)** | `SwiftEventBus` + `EventDispatcher` | Events posted to both systems for backward compatibility |
**Key Caching:** Encryption key cached in memory for 300 seconds (5 min) to reduce Keychain lookups.
**Encrypted Token Storage:** When encryption is enabled, tokens are stored as Base64-encoded encrypted data in the database. The system detects encrypted vs. plain text by checking if data is valid Base64 but NOT a JWT (JWTs start with "eyJ").
**Validation:** Each config struct has a `validate()` method that throws `ConfigurationError` with specific error types and recovery suggestions.
**Serialization:**`WarplyConfiguration` is `Codable` — can be saved/loaded as JSON via `toJSONData()`, `fromJSONData()`, `saveToFile(at:)`, `loadFromFile(at:)`.
## 11. Data Models
All models use **dictionary-based initialization** (`init(dictionary: [String: Any])`) to parse JSON responses.
Custom fonts bundled: **PingLCG** family (Bold, Light, Regular) in `.otf` format.
### Bundle Resource Loading
Framework resources loaded via `Bundle.frameworkBundle` (defined in `XIBLoader.swift`/`MyEmptyClass.swift`), which resolves the correct bundle whether using CocoaPods resource bundles or SPM.