|
| 1 | +package to.bitkit.paykit |
| 2 | + |
| 3 | +import android.content.Context |
| 4 | +import android.content.SharedPreferences |
| 5 | +import to.bitkit.utils.Logger |
| 6 | + |
| 7 | +/** |
| 8 | + * Feature flags for Paykit integration. |
| 9 | + * |
| 10 | + * Use these flags to control the rollout of Paykit features |
| 11 | + * and enable quick rollback if issues arise. |
| 12 | + */ |
| 13 | +object PaykitFeatureFlags { |
| 14 | + |
| 15 | + private const val TAG = "PaykitFeatureFlags" |
| 16 | + private const val PREFS_NAME = "paykit_feature_flags" |
| 17 | + |
| 18 | + private const val ENABLED_KEY = "paykit_enabled" |
| 19 | + private const val LIGHTNING_ENABLED_KEY = "paykit_lightning_enabled" |
| 20 | + private const val ONCHAIN_ENABLED_KEY = "paykit_onchain_enabled" |
| 21 | + private const val RECEIPT_STORAGE_ENABLED_KEY = "paykit_receipt_storage_enabled" |
| 22 | + |
| 23 | + private var prefs: SharedPreferences? = null |
| 24 | + |
| 25 | + /** |
| 26 | + * Initialize feature flags with application context. |
| 27 | + * Call this during Application.onCreate(). |
| 28 | + */ |
| 29 | + fun init(context: Context) { |
| 30 | + prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) |
| 31 | + setDefaults() |
| 32 | + } |
| 33 | + |
| 34 | + // MARK: - Main Feature Flag |
| 35 | + |
| 36 | + /** Whether Paykit integration is enabled. */ |
| 37 | + var isEnabled: Boolean |
| 38 | + get() = prefs?.getBoolean(ENABLED_KEY, false) ?: false |
| 39 | + set(value) = prefs?.edit()?.putBoolean(ENABLED_KEY, value)?.apply() ?: Unit |
| 40 | + |
| 41 | + /** Whether Lightning payments via Paykit are enabled. */ |
| 42 | + var isLightningEnabled: Boolean |
| 43 | + get() = prefs?.getBoolean(LIGHTNING_ENABLED_KEY, true) ?: true |
| 44 | + set(value) = prefs?.edit()?.putBoolean(LIGHTNING_ENABLED_KEY, value)?.apply() ?: Unit |
| 45 | + |
| 46 | + /** Whether on-chain payments via Paykit are enabled. */ |
| 47 | + var isOnchainEnabled: Boolean |
| 48 | + get() = prefs?.getBoolean(ONCHAIN_ENABLED_KEY, true) ?: true |
| 49 | + set(value) = prefs?.edit()?.putBoolean(ONCHAIN_ENABLED_KEY, value)?.apply() ?: Unit |
| 50 | + |
| 51 | + /** Whether receipt storage is enabled. */ |
| 52 | + var isReceiptStorageEnabled: Boolean |
| 53 | + get() = prefs?.getBoolean(RECEIPT_STORAGE_ENABLED_KEY, true) ?: true |
| 54 | + set(value) = prefs?.edit()?.putBoolean(RECEIPT_STORAGE_ENABLED_KEY, value)?.apply() ?: Unit |
| 55 | + |
| 56 | + // MARK: - Remote Config |
| 57 | + |
| 58 | + /** |
| 59 | + * Update flags from remote config. |
| 60 | + * Call this during app startup to sync with server-side configuration. |
| 61 | + * |
| 62 | + * @param config Map from remote config service (Firebase Remote Config, etc.) |
| 63 | + */ |
| 64 | + fun updateFromRemoteConfig(config: Map<String, Any>) { |
| 65 | + (config["paykit_enabled"] as? Boolean)?.let { isEnabled = it } |
| 66 | + (config["paykit_lightning_enabled"] as? Boolean)?.let { isLightningEnabled = it } |
| 67 | + (config["paykit_onchain_enabled"] as? Boolean)?.let { isOnchainEnabled = it } |
| 68 | + (config["paykit_receipt_storage_enabled"] as? Boolean)?.let { isReceiptStorageEnabled = it } |
| 69 | + } |
| 70 | + |
| 71 | + // MARK: - Defaults |
| 72 | + |
| 73 | + /** Set default values for all flags. */ |
| 74 | + private fun setDefaults() { |
| 75 | + prefs?.let { p -> |
| 76 | + if (!p.contains(ENABLED_KEY)) { |
| 77 | + p.edit() |
| 78 | + .putBoolean(ENABLED_KEY, false) // Disabled by default until ready |
| 79 | + .putBoolean(LIGHTNING_ENABLED_KEY, true) |
| 80 | + .putBoolean(ONCHAIN_ENABLED_KEY, true) |
| 81 | + .putBoolean(RECEIPT_STORAGE_ENABLED_KEY, true) |
| 82 | + .apply() |
| 83 | + } |
| 84 | + } |
| 85 | + } |
| 86 | + |
| 87 | + // MARK: - Rollback |
| 88 | + |
| 89 | + /** |
| 90 | + * Emergency rollback - disable all Paykit features. |
| 91 | + * Call this if critical issues are detected. |
| 92 | + */ |
| 93 | + fun emergencyRollback() { |
| 94 | + isEnabled = false |
| 95 | + Logger.warn("Paykit emergency rollback triggered", context = TAG) |
| 96 | + |
| 97 | + // Reset manager state |
| 98 | + PaykitManager.getInstance().reset() |
| 99 | + } |
| 100 | +} |
| 101 | + |
| 102 | +/** |
| 103 | + * Manages Paykit configuration for production deployment. |
| 104 | + */ |
| 105 | +object PaykitConfigManager { |
| 106 | + |
| 107 | + private const val TAG = "PaykitConfigManager" |
| 108 | + |
| 109 | + // MARK: - Environment |
| 110 | + |
| 111 | + /** Current environment configuration. */ |
| 112 | + val environment: PaykitEnvironment |
| 113 | + get() = if (to.bitkit.BuildConfig.DEBUG) { |
| 114 | + PaykitEnvironment.DEVELOPMENT |
| 115 | + } else { |
| 116 | + PaykitEnvironment.PRODUCTION |
| 117 | + } |
| 118 | + |
| 119 | + // MARK: - Logging |
| 120 | + |
| 121 | + /** Log level for Paykit operations. */ |
| 122 | + var logLevel: PaykitLogLevel = PaykitLogLevel.INFO |
| 123 | + |
| 124 | + /** Whether to log payment details (disable in production for privacy). */ |
| 125 | + val logPaymentDetails: Boolean |
| 126 | + get() = to.bitkit.BuildConfig.DEBUG |
| 127 | + |
| 128 | + // MARK: - Timeouts |
| 129 | + |
| 130 | + /** Default payment timeout in milliseconds. */ |
| 131 | + var defaultPaymentTimeoutMs: Long = 60_000L |
| 132 | + |
| 133 | + /** Lightning payment polling interval in milliseconds. */ |
| 134 | + var lightningPollingIntervalMs: Long = 500L |
| 135 | + |
| 136 | + // MARK: - Retry Configuration |
| 137 | + |
| 138 | + /** Maximum number of retry attempts for failed payments. */ |
| 139 | + var maxRetryAttempts: Int = 3 |
| 140 | + |
| 141 | + /** Base delay between retries in milliseconds. */ |
| 142 | + var retryBaseDelayMs: Long = 1000L |
| 143 | + |
| 144 | + // MARK: - Monitoring |
| 145 | + |
| 146 | + /** |
| 147 | + * Error reporting callback. |
| 148 | + * Set this to integrate with your error monitoring service. |
| 149 | + */ |
| 150 | + var errorReporter: ((Throwable, Map<String, Any>?) -> Unit)? = null |
| 151 | + |
| 152 | + /** Report an error to the configured monitoring service. */ |
| 153 | + fun reportError(error: Throwable, context: Map<String, Any>? = null) { |
| 154 | + errorReporter?.invoke(error, context) |
| 155 | + } |
| 156 | +} |
| 157 | + |
| 158 | +/** Paykit environment configuration. */ |
| 159 | +enum class PaykitEnvironment { |
| 160 | + DEVELOPMENT, |
| 161 | + STAGING, |
| 162 | + PRODUCTION |
| 163 | +} |
| 164 | + |
| 165 | +/** Log level for Paykit operations. */ |
| 166 | +enum class PaykitLogLevel { |
| 167 | + DEBUG, |
| 168 | + INFO, |
| 169 | + WARNING, |
| 170 | + ERROR, |
| 171 | + NONE |
| 172 | +} |
0 commit comments