@circle-fin/w3s-pw-react-native-sdk 1.1.7 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/BARE_REACT_NATIVE_GUIDE.md +397 -0
  2. package/LICENSE +1 -1
  3. package/README.md +196 -90
  4. package/android/build.gradle +43 -126
  5. package/android/src/main/AndroidManifest.xml +12 -16
  6. package/android/src/main/java/com/circlefin/programmablewalletrnsdk/ProgrammablewalletRnSdkModule.kt +414 -244
  7. package/android/src/main/java/com/circlefin/programmablewalletrnsdk/PromiseCallback.kt +76 -74
  8. package/android/src/main/java/com/circlefin/programmablewalletrnsdk/RecordsHelper.kt +602 -0
  9. package/android/src/main/java/com/circlefin/programmablewalletrnsdk/models/Records.kt +43 -0
  10. package/android/src/main/java/com/circlefin/programmablewalletrnsdk/pwcustom/RnImageSetter.kt +55 -33
  11. package/android/src/main/java/com/circlefin/programmablewalletrnsdk/pwcustom/RnLayoutProvider.kt +81 -79
  12. package/android/src/main/java/com/circlefin/programmablewalletrnsdk/pwcustom/RnViewSetterProvider.kt +93 -63
  13. package/app.json +8 -0
  14. package/build/ProgrammablewalletRnSdkModule.d.ts +44 -0
  15. package/build/ProgrammablewalletRnSdkModule.d.ts.map +1 -0
  16. package/build/ProgrammablewalletRnSdkModule.js +21 -0
  17. package/build/ProgrammablewalletRnSdkModule.js.map +1 -0
  18. package/build/WalletSdk.d.ts +20 -0
  19. package/build/WalletSdk.d.ts.map +1 -0
  20. package/build/WalletSdk.js +303 -0
  21. package/build/WalletSdk.js.map +1 -0
  22. package/build/bridgeSafe.d.ts +50 -0
  23. package/build/bridgeSafe.d.ts.map +1 -0
  24. package/build/bridgeSafe.js +136 -0
  25. package/build/bridgeSafe.js.map +1 -0
  26. package/build/index.d.ts +21 -0
  27. package/build/index.d.ts.map +1 -0
  28. package/build/index.js +21 -0
  29. package/build/index.js.map +1 -0
  30. package/{lib/typescript/src → build}/types.d.ts +72 -43
  31. package/build/types.d.ts.map +1 -0
  32. package/build/types.js +331 -0
  33. package/build/types.js.map +1 -0
  34. package/build/utils/securityQuestionUtils.d.ts +43 -0
  35. package/build/utils/securityQuestionUtils.d.ts.map +1 -0
  36. package/build/utils/securityQuestionUtils.js +109 -0
  37. package/build/utils/securityQuestionUtils.js.map +1 -0
  38. package/expo-module.config.json +11 -0
  39. package/ios/Array+Extension.swift +17 -15
  40. package/ios/BridgeHelper.swift +71 -92
  41. package/ios/{RnWalletSdk+CustomizeAdapter.swift → CustomizeAdapter.swift} +19 -29
  42. package/ios/ProgrammablewalletRnSdk.podspec +30 -0
  43. package/ios/ProgrammablewalletRnSdkModule.swift +384 -0
  44. package/ios/TextConfig.swift +17 -15
  45. package/ios/TextKey.swift +17 -15
  46. package/ios/UIApplication+Extension.swift +26 -17
  47. package/ios/UIColor+Extension.swift +34 -28
  48. package/ios/UITextField+Extension.swift +31 -0
  49. package/ios/UIView+Extension.swift +24 -17
  50. package/package.json +70 -116
  51. package/plugins/apple-signin-entitlements.js +16 -0
  52. package/plugins/infoplist-config.js +77 -0
  53. package/plugins/infoplist-config.md +72 -0
  54. package/plugins/podfile-modifier.js +84 -0
  55. package/plugins/podfile-modifier.md +33 -0
  56. package/plugins/withCopyFiles.js +132 -0
  57. package/plugins/withCopyFiles.md +81 -0
  58. package/src/ProgrammablewalletRnSdkModule.ts +68 -38
  59. package/src/WalletSdk.ts +297 -159
  60. package/src/bridgeSafe.ts +156 -0
  61. package/src/index.ts +21 -0
  62. package/src/types.ts +133 -110
  63. package/src/utils/securityQuestionUtils.ts +121 -0
  64. package/COPYRIGHT +0 -10
  65. package/android/gradle.properties +0 -21
  66. package/android/src/main/AndroidManifestNew.xml +0 -22
  67. package/android/src/main/java/com/circlefin/programmablewalletrnsdk/BridgeHelper.kt +0 -399
  68. package/android/src/main/java/com/circlefin/programmablewalletrnsdk/ProgrammablewalletRnSdkPackage.kt +0 -49
  69. package/android/src/main/java/com/circlefin/programmablewalletrnsdk/PromiseCallback2.kt +0 -65
  70. package/android/src/main/java/com/circlefin/programmablewalletrnsdk/PromiseLogoutCallback.kt +0 -47
  71. package/android/src/main/java/com/circlefin/programmablewalletrnsdk/PromiseSocialCallback.kt +0 -53
  72. package/android/src/main/java/com/circlefin/programmablewalletrnsdk/TestHelper.kt +0 -37
  73. package/android/src/main/java/com/circlefin/programmablewalletrnsdk/annotation/ExcludeFromGeneratedCCReport.kt +0 -33
  74. package/android/src/newarch/ProgrammablewalletRnSdkSpec.kt +0 -29
  75. package/android/src/oldarch/ProgrammablewalletRnSdkSpec.kt +0 -76
  76. package/circlefin-w3s-pw-react-native-sdk.podspec +0 -41
  77. package/ios/EventEmitter.swift +0 -49
  78. package/ios/ProgrammablewalletRnSdk.h +0 -29
  79. package/ios/ProgrammablewalletRnSdk.mm +0 -162
  80. package/ios/ReactNativeEventEmitter.m +0 -27
  81. package/ios/ReactNativeEventEmitter.swift +0 -37
  82. package/ios/RnWalletSdk.swift +0 -390
  83. package/ios/programmablewallet-rn-sdk-Bridging-Header.h +0 -22
  84. package/lib/commonjs/NativeProgrammablewalletRnSdk.js +0 -24
  85. package/lib/commonjs/NativeProgrammablewalletRnSdk.js.map +0 -1
  86. package/lib/commonjs/ProgrammablewalletRnSdkModule.js +0 -38
  87. package/lib/commonjs/ProgrammablewalletRnSdkModule.js.map +0 -1
  88. package/lib/commonjs/WalletSdk.js +0 -211
  89. package/lib/commonjs/WalletSdk.js.map +0 -1
  90. package/lib/commonjs/index.js +0 -74
  91. package/lib/commonjs/index.js.map +0 -1
  92. package/lib/commonjs/types.js +0 -342
  93. package/lib/commonjs/types.js.map +0 -1
  94. package/lib/module/NativeProgrammablewalletRnSdk.js +0 -19
  95. package/lib/module/NativeProgrammablewalletRnSdk.js.map +0 -1
  96. package/lib/module/ProgrammablewalletRnSdkModule.js +0 -31
  97. package/lib/module/ProgrammablewalletRnSdkModule.js.map +0 -1
  98. package/lib/module/WalletSdk.js +0 -203
  99. package/lib/module/WalletSdk.js.map +0 -1
  100. package/lib/module/index.js +0 -18
  101. package/lib/module/index.js.map +0 -1
  102. package/lib/module/types.js +0 -334
  103. package/lib/module/types.js.map +0 -1
  104. package/lib/typescript/src/NativeProgrammablewalletRnSdk.d.ts +0 -28
  105. package/lib/typescript/src/NativeProgrammablewalletRnSdk.d.ts.map +0 -1
  106. package/lib/typescript/src/ProgrammablewalletRnSdkModule.d.ts +0 -3
  107. package/lib/typescript/src/ProgrammablewalletRnSdkModule.d.ts.map +0 -1
  108. package/lib/typescript/src/WalletSdk.d.ts +0 -3
  109. package/lib/typescript/src/WalletSdk.d.ts.map +0 -1
  110. package/lib/typescript/src/index.d.ts +0 -4
  111. package/lib/typescript/src/index.d.ts.map +0 -1
  112. package/lib/typescript/src/types.d.ts.map +0 -1
  113. package/src/NativeProgrammablewalletRnSdk.ts +0 -77
  114. package/src/index.tsx +0 -29
@@ -0,0 +1,384 @@
1
+ /*
2
+ * Copyright 2025 Circle Internet Group, Inc. All rights reserved.
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ import ExpoModulesCore
20
+ import CircleProgrammableWalletSDK
21
+
22
+ let CIRCLE_PW_ON_EVENT_NAME = "CirclePwOnEvent"
23
+ let CIRCLE_PW_ON_SUCCESS_EVENT_NAME = "CirclePwOnSuccess"
24
+ let CIRCLE_PW_ON_ERROR_EVENT_NAME = "CirclePwOnError"
25
+
26
+ public class ProgrammablewalletRnSdkModule: Module {
27
+
28
+ var sLocal: [ImageStore.Img: UIImage] = [:]
29
+ var sRemote: [ImageStore.Img: URL] = [:]
30
+ var sQuestions: [SecurityQuestion] = []
31
+ var sTextsMap: [TextsKey: [TextConfig]] = [:]
32
+ var sTextMap: [TextKey: TextConfig] = [:]
33
+ var sSecurityConfirmItemAndConfigs: ([SecurityConfirmItem], [TextConfig]) = ([], [])
34
+ var sDismissOnCallbackMap: [Int: Bool] = [:]
35
+ var sErrorStringMap: [Int: String] = [:]
36
+ var sdkNavigationController: UINavigationController?
37
+ var sDateFormat = "yyyy-MM-dd"
38
+
39
+ // Each module class must implement the definition function. The definition consists of components
40
+ // that describes the module's functionality and behavior.
41
+ // See https://docs.expo.dev/modules/module-api for more details about available components.
42
+ public func definition() -> ModuleDefinition {
43
+ // Sets the name of the module that JavaScript code will use to refer to the module. Takes a string as an argument.
44
+ // Can be inferred from module's class name, but it's recommended to set it explicitly for clarity.
45
+ // The module will be accessible from `requireNativeModule('ProgrammablewalletRnSdk')` in JavaScript.
46
+ Name("ProgrammablewalletRnSdk")
47
+
48
+ Events(CIRCLE_PW_ON_EVENT_NAME, CIRCLE_PW_ON_SUCCESS_EVENT_NAME, CIRCLE_PW_ON_ERROR_EVENT_NAME)
49
+
50
+ // Sets constant properties on the module. Can take a dictionary or a closure that returns a dictionary.
51
+ Constants([
52
+ "sdkVersion": WalletSdk.shared.sdkVersion()
53
+ ])
54
+
55
+ // Defines a JavaScript synchronous function that runs the native code on the JavaScript thread.
56
+ Function("getDeviceId") {
57
+ return WalletSdk.shared.getDeviceId()
58
+ }
59
+
60
+ // Initialize SDK with configuration
61
+ AsyncFunction("initSdk") { (configuration: [String: Any]) async throws -> Void in
62
+
63
+ WalletSdk.shared.setLayoutProvider(self)
64
+ WalletSdk.shared.setDelegate(self)
65
+ WalletSdk.shared.setErrorMessenger(self)
66
+
67
+ var endPoint = configuration["endpoint"] as? String ?? ""
68
+ if endPoint.last == "/" {
69
+ endPoint.removeLast()
70
+ }
71
+ let appId = configuration["appId"] as? String ?? ""
72
+
73
+ var enableBiometricsPin = false
74
+ if let settingsManagement = configuration["settingsManagement"] as? [String: Any],
75
+ let enableBio = settingsManagement["enableBiometricsPin"] as? Bool {
76
+ enableBiometricsPin = enableBio
77
+ }
78
+
79
+ let settings = WalletSdk.SettingsManagement(enableBiometricsPin: enableBiometricsPin)
80
+ let sdkConfig = WalletSdk.Configuration(endPoint: endPoint, appId: appId, settingsManagement: settings)
81
+
82
+ try WalletSdk.shared.setConfiguration(sdkConfig)
83
+ return
84
+ }
85
+
86
+ // Set security questions for the wallet
87
+ Function("setSecurityQuestions") { (securityQuestions: [[String: Any]]) in
88
+ sQuestions = BridgeHelper.getSecurityQuestions(securityQuestions)
89
+ }
90
+
91
+ // Execute wallet operations
92
+ AsyncFunction("execute") { (userToken: String, encryptionKey: String, challengeIds: [String], promise: Promise) in
93
+ DispatchQueue.main.async {
94
+ WalletSdk.shared.execute(userToken: userToken,
95
+ encryptionKey: encryptionKey,
96
+ challengeIds: challengeIds) { executeCompletion in
97
+ self._bridgeExecuteCompletion(executeCompletion, promise)
98
+ }
99
+ }
100
+ }
101
+
102
+ AsyncFunction("verifyOTP") { (otpToken: String,
103
+ deviceToken: String,
104
+ deviceEncryptionKey: String,
105
+ promise: Promise) in
106
+ DispatchQueue.main.async {
107
+ WalletSdk.shared.verifyOTP(deviceToken: deviceToken,
108
+ encryptionKey: deviceEncryptionKey,
109
+ otpToken: otpToken) { loginCompletion in
110
+ switch loginCompletion.result {
111
+ case .success(let loginResult):
112
+ self._handleLoginResultExpo(
113
+ result: loginResult,
114
+ resolve: { value in promise.resolve(value) }
115
+ )
116
+ case .failure(let error):
117
+ self._handleErrorResultExpo(
118
+ error: error,
119
+ controller: loginCompletion.onErrorController,
120
+ reject: { code, description in promise.reject(code, description) }
121
+ )
122
+ }
123
+ }
124
+ }
125
+ }
126
+
127
+ AsyncFunction("performLogin") { (provider: String,
128
+ deviceToken: String,
129
+ deviceEncryptionKey: String,
130
+ promise: Promise) in
131
+ guard let socialProvider = SocialProvider(rawValue: provider) else {
132
+ promise.reject("155720", "[unknown format] invalid provider string")
133
+ return
134
+ }
135
+ DispatchQueue.main.async {
136
+ WalletSdk.shared.performLogin(provider: socialProvider,
137
+ deviceToken: deviceToken,
138
+ encryptionKey: deviceEncryptionKey) { loginCompletion in
139
+ switch loginCompletion.result {
140
+ case .success(let loginResult):
141
+ self._handleLoginResultExpo(
142
+ result: loginResult,
143
+ resolve: { value in promise.resolve(value) }
144
+ )
145
+ case .failure(let error):
146
+ promise.reject(String(error.errorCode.rawValue), error.displayString)
147
+ }
148
+ }
149
+ }
150
+ }
151
+
152
+ AsyncFunction("performLogout") { (provider: String, promise: Promise) in
153
+ guard let socialProvider = SocialProvider(rawValue: provider) else {
154
+ promise.reject("155720", "[unknown format] invalid provider string")
155
+ return
156
+ }
157
+ DispatchQueue.main.async {
158
+ WalletSdk.shared.performLogout(provider: socialProvider) { _ in
159
+ promise.resolve(nil)
160
+ }
161
+ }
162
+ }
163
+
164
+ AsyncFunction("setBiometricsPin") { (userToken: String,
165
+ encryptionKey: String,
166
+ promise: Promise) in
167
+ DispatchQueue.main.async {
168
+ WalletSdk.shared.setBiometricsPin(userToken: userToken, encryptionKey: encryptionKey) { executeCompletion in
169
+ self._bridgeExecuteCompletion(executeCompletion, promise)
170
+ }
171
+ }
172
+ }
173
+
174
+ // Set dismiss on callback map for error handling
175
+ Function("setDismissOnCallbackMap") { (mapData: [String: Bool]) in
176
+ sDismissOnCallbackMap = BridgeHelper.getDismissOnCallbackMap(mapData)
177
+ }
178
+
179
+ Function("moveTaskToFront") {
180
+ DispatchQueue.main.async {
181
+ guard let sdkVc = self.sdkNavigationController else { return }
182
+ let topMostVC = UIApplication.shared.topMostViewController()
183
+ sdkVc.modalPresentationStyle = .overFullScreen
184
+ topMostVC?.present(sdkVc, animated: true)
185
+ print("moveTaskToFront")
186
+ }
187
+ }
188
+
189
+ Function("moveRnTaskToFront") {
190
+ DispatchQueue.main.async {
191
+ guard let sdkVc = self.sdkNavigationController else { return }
192
+ sdkVc.dismiss(animated: true)
193
+ print("moveRnTaskToFront")
194
+ }
195
+ }
196
+
197
+ // Set text configurations map
198
+ Function("setTextConfigsMap") { (mapData: [String: Any]) in
199
+ sTextsMap = BridgeHelper.getTextsMap(mapData)
200
+ }
201
+
202
+ // Set icon text configurations map
203
+ Function("setIconTextConfigsMap") { (mapData: [String: Any]) in
204
+ sSecurityConfirmItemAndConfigs = BridgeHelper.getSecurityConfirmItemAndConfigs(mapData)
205
+ }
206
+
207
+ // Set text configuration map
208
+ Function("setTextConfigMap") { (mapData: [String: Any]) in
209
+ sTextMap = BridgeHelper.getTextMap(mapData)
210
+ }
211
+
212
+ // Set image map for custom images
213
+ Function("setImageMap") { (mapData: [String: String]) in
214
+ for (key, value) in mapData {
215
+ guard let imgUrl = URL(string: value),
216
+ let imgKey = BridgeHelper.getImageKey(rnKey: key) else { continue }
217
+ sRemote[imgKey] = imgUrl
218
+ }
219
+ }
220
+
221
+ // Set date format for display
222
+ Function("setDateFormat") { (format: String) in
223
+ sDateFormat = format
224
+ }
225
+
226
+ // Set debugging (no implementation is needed on the iOS side.)
227
+ Function("setDebugging") { (debugging: Bool) in
228
+ // No-op on iOS
229
+ }
230
+
231
+ // Register setCustomUserAgent
232
+ Function("setCustomUserAgent") { (userAgent: String) in
233
+ WalletSdk.shared.customUserAgent = userAgent
234
+ }
235
+
236
+ // Set error string map for custom error messages
237
+ Function("setErrorStringMap") { (mapData: [String: String]) in
238
+ sErrorStringMap = BridgeHelper.getErrorStringMap(mapData)
239
+ }
240
+ }
241
+ }
242
+
243
+ extension ProgrammablewalletRnSdkModule: WalletSdkLayoutProvider {
244
+
245
+ public func securityQuestions() -> [SecurityQuestion] {
246
+ return sQuestions
247
+ }
248
+
249
+ public func securityQuestionsRequiredCount() -> Int {
250
+ return sTextsMap[.securityQuestionHeaders]?.count ?? 2
251
+ }
252
+
253
+ public func securityConfirmItems() -> [SecurityConfirmItem] {
254
+ return sSecurityConfirmItemAndConfigs.0
255
+ }
256
+
257
+ public func displayDateFormat() -> String {
258
+ return sDateFormat
259
+ }
260
+
261
+ public func imageStore() -> ImageStore {
262
+ return ImageStore(local: sLocal, remote: sRemote)
263
+ }
264
+ }
265
+
266
+ extension ProgrammablewalletRnSdkModule: WalletSdkDelegate {
267
+
268
+ public func walletSdk(willPresentController controller: UIViewController) {
269
+ self.customizeAdapter(controller: controller)
270
+ }
271
+
272
+ public func walletSdk(controller: UIViewController, onForgetPINButtonSelected onSelect: Void) {
273
+ self.sdkNavigationController = controller.navigationController
274
+ self.sendEvent(CIRCLE_PW_ON_EVENT_NAME, ["name": "forgotPin"])
275
+ }
276
+ }
277
+
278
+ extension ProgrammablewalletRnSdkModule: ErrorMessenger {
279
+
280
+ public func getErrorString(_ code: CircleProgrammableWalletSDK.ApiError.ErrorCode) -> String? {
281
+ return BridgeHelper.getErrorString(code.rawValue, sErrorStringMap[code.rawValue], sTextMap)
282
+ }
283
+ }
284
+
285
+ private extension ProgrammablewalletRnSdkModule {
286
+ func _handleExecuteResultExpo(result: ExecuteResult,
287
+ onWarning: ExecuteWarning?,
288
+ controller: UIViewController?,
289
+ resolve: @escaping ([String: Any]) -> Void) {
290
+ let challengeStatus = result.status.rawValue
291
+ let challengeType = result.resultType.rawValue
292
+ var dismiss = false
293
+
294
+ let dataDict: [String: Any] = [
295
+ "signature": result.data?.signature,
296
+ "signedTransaction": result.data?.signedTransaction,
297
+ "txHash": result.data?.txHash
298
+ ].compactMapValues { $0 }
299
+
300
+ var dict: [String: Any] = [
301
+ "result": [
302
+ "status": challengeStatus,
303
+ "resultType": challengeType,
304
+ "data": dataDict
305
+ ]
306
+ ]
307
+ if let onWarning = onWarning {
308
+ dict["warning"] = [
309
+ "warningType": onWarning.warningType.rawValue,
310
+ "warningString": onWarning.warningString
311
+ ]
312
+ dismiss = self.sDismissOnCallbackMap[onWarning.warningType.rawValue] == true
313
+ }
314
+ if dismiss {
315
+ controller?.dismiss(animated: true) {
316
+ resolve(dict)
317
+ }
318
+ } else {
319
+ self.sendEvent(CIRCLE_PW_ON_SUCCESS_EVENT_NAME, dict)
320
+ }
321
+ }
322
+
323
+ func _handleLoginResultExpo(result: LoginResult,
324
+ resolve: @escaping ([String: Any]) -> Void) {
325
+ var oauthInfoDict: [String: Any]?
326
+ if let oauthInfo = result.oauthInfo {
327
+ oauthInfoDict = [
328
+ "provider": oauthInfo.provider,
329
+ "scope": oauthInfo.scope as Any,
330
+ "socialUserUUID": oauthInfo.socialUserUUID,
331
+ "socialUserInfo": [
332
+ "name": oauthInfo.socialUserInfo?.name,
333
+ "email": oauthInfo.socialUserInfo?.email,
334
+ "phone": oauthInfo.socialUserInfo?.phone,
335
+ ]
336
+ ]
337
+ }
338
+ let dict: [String: Any] = [
339
+ "userToken": result.userToken,
340
+ "encryptionKey": result.encryptionKey,
341
+ "refreshToken": result.refreshToken,
342
+ "oauthInfo": oauthInfoDict as Any
343
+ ]
344
+ resolve(dict)
345
+ }
346
+
347
+ func _handleErrorResultExpo(error: ApiError,
348
+ controller: UIViewController?,
349
+ reject: @escaping (String, String) -> Void) {
350
+ if self.sDismissOnCallbackMap[error.errorCode.rawValue] == true {
351
+ controller?.dismiss(animated: true)
352
+
353
+ let code = String(error.errorCode.rawValue)
354
+ let message = error.displayString
355
+ reject(code, message)
356
+
357
+ } else {
358
+ let dict: [String: Any] = [
359
+ "code": String(error.errorCode.rawValue),
360
+ "message": error.displayString
361
+ ]
362
+ self.sendEvent(CIRCLE_PW_ON_ERROR_EVENT_NAME, dict)
363
+ }
364
+ }
365
+
366
+ func _bridgeExecuteCompletion(_ executeCompletion: CircleProgrammableWalletSDK.ExecuteCompletionStruct,
367
+ _ promise: Promise) {
368
+ switch executeCompletion.result {
369
+ case .success(let executeResult):
370
+ self._handleExecuteResultExpo(
371
+ result: executeResult,
372
+ onWarning: executeCompletion.onWarning,
373
+ controller: executeCompletion.onErrorController,
374
+ resolve: { value in promise.resolve(value) }
375
+ )
376
+ case .failure(let error):
377
+ self._handleErrorResultExpo(
378
+ error: error,
379
+ controller: executeCompletion.onErrorController,
380
+ reject: { code, description in promise.reject(code, description) }
381
+ )
382
+ }
383
+ }
384
+ }
@@ -1,18 +1,20 @@
1
- // Copyright (c) 2024, Circle Internet Financial, LTD. All rights reserved.
2
- //
3
- // SPDX-License-Identifier: Apache-2.0
4
- //
5
- // Licensed under the Apache License, Version 2.0 (the "License");
6
- // you may not use this file except in compliance with the License.
7
- // You may obtain a copy of the License at
8
- //
9
- // http://www.apache.org/licenses/LICENSE-2.0
10
- //
11
- // Unless required by applicable law or agreed to in writing, software
12
- // distributed under the License is distributed on an "AS IS" BASIS,
13
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- // See the License for the specific language governing permissions and
15
- // limitations under the License.
1
+ /*
2
+ * Copyright 2025 Circle Internet Group, Inc. All rights reserved.
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
16
18
 
17
19
  import Foundation
18
20
 
package/ios/TextKey.swift CHANGED
@@ -1,18 +1,20 @@
1
- // Copyright (c) 2024, Circle Internet Financial, LTD. All rights reserved.
2
- //
3
- // SPDX-License-Identifier: Apache-2.0
4
- //
5
- // Licensed under the Apache License, Version 2.0 (the "License");
6
- // you may not use this file except in compliance with the License.
7
- // You may obtain a copy of the License at
8
- //
9
- // http://www.apache.org/licenses/LICENSE-2.0
10
- //
11
- // Unless required by applicable law or agreed to in writing, software
12
- // distributed under the License is distributed on an "AS IS" BASIS,
13
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- // See the License for the specific language governing permissions and
15
- // limitations under the License.
1
+ /*
2
+ * Copyright 2025 Circle Internet Group, Inc. All rights reserved.
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
16
18
 
17
19
  enum TextsKey: String {
18
20
  case newPinCodeHeadline
@@ -1,25 +1,34 @@
1
- // Copyright (c) 2024, Circle Internet Financial, LTD. All rights reserved.
2
- //
3
- // SPDX-License-Identifier: Apache-2.0
4
- //
5
- // Licensed under the Apache License, Version 2.0 (the "License");
6
- // you may not use this file except in compliance with the License.
7
- // You may obtain a copy of the License at
8
- //
9
- // http://www.apache.org/licenses/LICENSE-2.0
10
- //
11
- // Unless required by applicable law or agreed to in writing, software
12
- // distributed under the License is distributed on an "AS IS" BASIS,
13
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- // See the License for the specific language governing permissions and
15
- // limitations under the License.
1
+ /*
2
+ * Copyright 2025 Circle Internet Group, Inc. All rights reserved.
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
16
18
 
17
19
  import UIKit
18
20
 
19
21
  extension UIApplication {
20
-
22
+
23
+ private var keyWindow: UIWindow? {
24
+ return connectedScenes
25
+ .compactMap { $0 as? UIWindowScene }
26
+ .flatMap { $0.windows }
27
+ .first { $0.isKeyWindow }
28
+ }
29
+
21
30
  func topMostViewController() -> UIViewController? {
22
- return UIApplication.shared.windows.filter { $0.isKeyWindow }.first?.rootViewController?.topMostViewController()
31
+ return keyWindow?.rootViewController?.topMostViewController()
23
32
  }
24
33
  }
25
34
 
@@ -1,23 +1,25 @@
1
- // Copyright (c) 2024, Circle Internet Financial, LTD. All rights reserved.
2
- //
3
- // SPDX-License-Identifier: Apache-2.0
4
- //
5
- // Licensed under the Apache License, Version 2.0 (the "License");
6
- // you may not use this file except in compliance with the License.
7
- // You may obtain a copy of the License at
8
- //
9
- // http://www.apache.org/licenses/LICENSE-2.0
10
- //
11
- // Unless required by applicable law or agreed to in writing, software
12
- // distributed under the License is distributed on an "AS IS" BASIS,
13
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- // See the License for the specific language governing permissions and
15
- // limitations under the License.
1
+ /*
2
+ * Copyright 2025 Circle Internet Group, Inc. All rights reserved.
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
16
18
 
17
19
  import UIKit
18
20
 
19
21
  extension UIColor {
20
-
22
+
21
23
  convenience init(_ string: String) {
22
24
  if string.hasPrefix("rgba(") {
23
25
  self.init(rgba: string)
@@ -25,7 +27,7 @@ extension UIColor {
25
27
  self.init(hex: string)
26
28
  }
27
29
  }
28
-
30
+
29
31
  /// Initialize UIColor with hex string
30
32
  ///
31
33
  /// - from: https://stackoverflow.com/a/59367504
@@ -33,16 +35,16 @@ extension UIColor {
33
35
  /// - Parameters:
34
36
  /// - hex: color hex string, ex: "#000" or "#000000" or "#00000000"
35
37
  convenience init(hex: String) {
36
-
38
+
37
39
  var hexFormatted: String = hex.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines).uppercased()
38
-
40
+
39
41
  if hexFormatted.hasPrefix("#") {
40
42
  hexFormatted = String(hexFormatted.dropFirst())
41
43
  }
42
-
44
+
43
45
  var argbValue: UInt64 = 0
44
46
  Scanner(string: hexFormatted).scanHexInt64(&argbValue)
45
-
47
+
46
48
  let a, r, g, b: UInt64
47
49
  switch hexFormatted.count {
48
50
  case 3: // RGB (12-bit)
@@ -64,33 +66,37 @@ extension UIColor {
64
66
  (a, r, g, b) = (255, 0, 0, 0)
65
67
  print("Invalid hex code used.")
66
68
  }
67
-
69
+
68
70
  self.init(red: CGFloat(r) / 255.0,
69
71
  green: CGFloat(g) / 255.0,
70
72
  blue: CGFloat(b) / 255.0,
71
73
  alpha: CGFloat(a) / 255.0)
72
74
  }
73
-
75
+
74
76
  /// Initialize UIColor with custom rgba string
75
77
  ///
76
78
  /// - Parameter rgba: custom rgba string, ex: "rgba(83,90,110,0.87)"
77
79
  convenience init(rgba: String) {
78
80
  guard rgba.hasPrefix("rgba(") else {
79
- fatalError("Invalid rgba format used.")
81
+ print("Invalid rgba format used. Defaulting to white color.")
82
+ self.init(white: 1, alpha: 1)
83
+ return
80
84
  }
81
-
85
+
82
86
  let arr = rgba.replacingOccurrences(of: "rgba(", with: "")
83
87
  .replacingOccurrences(of: ")", with: "")
84
88
  .split(separator: ",")
85
-
89
+
86
90
  guard arr.count == 4,
87
91
  let r = Double(arr[0]),
88
92
  let g = Double(arr[1]),
89
93
  let b = Double(arr[2]),
90
94
  let a = Double(arr[3]) else {
91
- fatalError("Invalid rgba format used.")
95
+ print("Invalid rgba format used. Defaulting to white color.")
96
+ self.init(white: 1, alpha: 1)
97
+ return
92
98
  }
93
-
99
+
94
100
  self.init(red: CGFloat(r) / 255.0,
95
101
  green: CGFloat(g) / 255.0,
96
102
  blue: CGFloat(b) / 255.0,
@@ -0,0 +1,31 @@
1
+ /*
2
+ * Copyright 2025 Circle Internet Group, Inc. All rights reserved.
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ import UIKit
20
+
21
+ extension UITextField {
22
+
23
+ func placeholderColor(color: UIColor) {
24
+ guard let placeholder = self.placeholder, let font = self.font else { return }
25
+ let attributeString = [
26
+ .foregroundColor: color,
27
+ .font: font,
28
+ ] as [NSAttributedString.Key: Any]
29
+ self.attributedPlaceholder = NSAttributedString(string: placeholder, attributes: attributeString)
30
+ }
31
+ }