framepayments-react-native 2.1.0 → 2.1.2

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 (83) hide show
  1. package/README.md +101 -74
  2. package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/framepayments/reactnativeframe/FrameCheckoutActivity$Companion.dex +0 -0
  3. package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/framepayments/reactnativeframe/FrameCheckoutActivity$tryShowCheckout$1.dex +0 -0
  4. package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/framepayments/reactnativeframe/FrameCheckoutActivity.dex +0 -0
  5. package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/framepayments/reactnativeframe/FrameFlowActivity$CartItemDto.dex +0 -0
  6. package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/framepayments/reactnativeframe/FrameFlowActivity$Companion.dex +0 -0
  7. package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/framepayments/reactnativeframe/FrameFlowActivity$parseCartItems$type$1.dex +0 -0
  8. package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/framepayments/reactnativeframe/FrameFlowActivity.dex +0 -0
  9. package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/framepayments/reactnativeframe/FrameGooglePayActivity$Companion.dex +0 -0
  10. package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/framepayments/reactnativeframe/FrameGooglePayActivity.dex +0 -0
  11. package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/framepayments/reactnativeframe/FrameOnboardingActivity$Companion.dex +0 -0
  12. package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/framepayments/reactnativeframe/FrameOnboardingActivity$parseCapabilities$type$1.dex +0 -0
  13. package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/framepayments/reactnativeframe/FrameOnboardingActivity.dex +0 -0
  14. package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/framepayments/reactnativeframe/FrameSDKModule.dex +0 -0
  15. package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
  16. package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -1
  17. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/framepayments/reactnativeframe/FrameCheckoutActivity$Companion.class +0 -0
  18. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/framepayments/reactnativeframe/FrameCheckoutActivity$tryShowCheckout$1.class +0 -0
  19. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/framepayments/reactnativeframe/FrameCheckoutActivity.class +0 -0
  20. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/framepayments/reactnativeframe/FrameFlowActivity$CartItemDto.class +0 -0
  21. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/framepayments/reactnativeframe/FrameFlowActivity$Companion.class +0 -0
  22. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/framepayments/reactnativeframe/FrameFlowActivity$parseCartItems$type$1.class +0 -0
  23. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/framepayments/reactnativeframe/FrameFlowActivity.class +0 -0
  24. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/framepayments/reactnativeframe/FrameGooglePayActivity$Companion.class +0 -0
  25. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/framepayments/reactnativeframe/FrameGooglePayActivity.class +0 -0
  26. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/framepayments/reactnativeframe/FrameOnboardingActivity$Companion.class +0 -0
  27. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/framepayments/reactnativeframe/FrameOnboardingActivity$parseCapabilities$type$1.class +0 -0
  28. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/framepayments/reactnativeframe/FrameOnboardingActivity.class +0 -0
  29. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/framepayments/reactnativeframe/FrameSDKModule.class +0 -0
  30. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab +0 -0
  31. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.values.at +0 -0
  32. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab +0 -0
  33. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at +0 -0
  34. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab +0 -0
  35. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream +0 -0
  36. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len +0 -0
  37. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len +0 -0
  38. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at +0 -0
  39. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i +0 -0
  40. package/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
  41. package/android/build/kotlin/compileDebugKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin +0 -0
  42. package/android/build/tmp/kotlin-classes/debug/com/framepayments/reactnativeframe/FrameCheckoutActivity$Companion.class +0 -0
  43. package/android/build/tmp/kotlin-classes/debug/com/framepayments/reactnativeframe/FrameCheckoutActivity$tryShowCheckout$1.class +0 -0
  44. package/android/build/tmp/kotlin-classes/debug/com/framepayments/reactnativeframe/FrameCheckoutActivity.class +0 -0
  45. package/android/build/tmp/kotlin-classes/debug/com/framepayments/reactnativeframe/FrameFlowActivity$CartItemDto.class +0 -0
  46. package/android/build/tmp/kotlin-classes/debug/com/framepayments/reactnativeframe/FrameFlowActivity$Companion.class +0 -0
  47. package/android/build/tmp/kotlin-classes/debug/com/framepayments/reactnativeframe/FrameFlowActivity$parseCartItems$type$1.class +0 -0
  48. package/android/build/tmp/kotlin-classes/debug/com/framepayments/reactnativeframe/FrameFlowActivity.class +0 -0
  49. package/android/build/tmp/kotlin-classes/debug/com/framepayments/reactnativeframe/FrameGooglePayActivity$Companion.class +0 -0
  50. package/android/build/tmp/kotlin-classes/debug/com/framepayments/reactnativeframe/FrameGooglePayActivity.class +0 -0
  51. package/android/build/tmp/kotlin-classes/debug/com/framepayments/reactnativeframe/FrameOnboardingActivity$Companion.class +0 -0
  52. package/android/build/tmp/kotlin-classes/debug/com/framepayments/reactnativeframe/FrameOnboardingActivity$parseCapabilities$type$1.class +0 -0
  53. package/android/build/tmp/kotlin-classes/debug/com/framepayments/reactnativeframe/FrameOnboardingActivity.class +0 -0
  54. package/android/build/tmp/kotlin-classes/debug/com/framepayments/reactnativeframe/FrameSDKModule.class +0 -0
  55. package/android/build.gradle +3 -3
  56. package/android/src/main/java/com/framepayments/reactnativeframe/FrameCheckoutActivity.kt +17 -13
  57. package/android/src/main/java/com/framepayments/reactnativeframe/FrameFlowActivity.kt +18 -11
  58. package/android/src/main/java/com/framepayments/reactnativeframe/FrameGooglePayActivity.kt +31 -8
  59. package/android/src/main/java/com/framepayments/reactnativeframe/FrameSDKModule.kt +37 -36
  60. package/ios/ApplePayPresenter.swift +53 -28
  61. package/ios/FrameRNTheme.swift +3 -24
  62. package/ios/FrameSDKBridge.m +10 -17
  63. package/ios/FrameSDKBridge.swift +89 -64
  64. package/lib/errors.d.ts +9 -1
  65. package/lib/errors.d.ts.map +1 -1
  66. package/lib/errors.js +9 -1
  67. package/lib/index.d.ts +4 -5
  68. package/lib/index.d.ts.map +1 -1
  69. package/lib/index.js +3 -4
  70. package/lib/native.d.ts +41 -13
  71. package/lib/native.d.ts.map +1 -1
  72. package/lib/native.js +64 -23
  73. package/lib/types.d.ts +18 -45
  74. package/lib/types.d.ts.map +1 -1
  75. package/package.json +1 -1
  76. package/src/__tests__/native.test.ts +179 -25
  77. package/src/errors.ts +9 -1
  78. package/src/index.ts +2 -7
  79. package/src/native.ts +83 -32
  80. package/src/types.ts +19 -58
  81. /package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_global-synthetics/com/framepayments/reactnativeframe/{FrameSDKModule$$InternalSyntheticLambda$2$984ab30558bc904ed37602fa6e3ebf28f1ed69df6712b31b00c4f26fc26d3b70$0.globals → FrameSDKModule$$InternalSyntheticLambda$2$7347ff5b95d03cf5be9ee5177309c1bf4be5faabda2bbedb79f5f4c91917c2b1$0.globals} +0 -0
  82. /package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_global-synthetics/com/framepayments/reactnativeframe/{FrameSDKModule$$InternalSyntheticLambda$2$f8d46f7169c404d37a1d505f19439b83090fbed62b5bdaf1e86717fdddebf622$0.globals → FrameSDKModule$$InternalSyntheticLambda$2$7347ff5b95d03cf5be9ee5177309c1bf4be5faabda2bbedb79f5f4c91917c2b1$1.globals} +0 -0
  83. /package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_global-synthetics/com/framepayments/reactnativeframe/{FrameSDKModule$$InternalSyntheticLambda$2$f8d46f7169c404d37a1d505f19439b83090fbed62b5bdaf1e86717fdddebf622$1.globals → FrameSDKModule$$InternalSyntheticLambda$2$9816d2cb3db63bf5efb3411b62dbb57847dd7ef82f88bae5f375baced7880f11$0.globals} +0 -0
@@ -20,34 +20,35 @@ public class FrameSDKBridge: NSObject {
20
20
  }
21
21
 
22
22
  @objc public
23
- func initialize(_ secretKey: String, publishableKey: String, debugMode: Bool, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
23
+ func initialize(_ secretKey: String, publishableKey: String, debugMode: Bool, theme: NSDictionary?, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
24
24
  DispatchQueue.main.async {
25
- FrameNetworking.shared.initializeWithAPIKey(secretKey, publishableKey: publishableKey, debugMode: debugMode)
25
+ let themeDict = theme as? [String: Any] ?? [:]
26
+ let resolvedTheme = themeDict.isEmpty ? FrameTheme.default : FrameRNTheme.parse(themeDict)
27
+ FrameNetworking.shared.initializeWithAPIKey(secretKey, publishableKey: publishableKey, theme: resolvedTheme, debugMode: debugMode)
26
28
  resolve(nil)
27
29
  }
28
30
  }
29
31
 
30
32
  @objc public
31
- func setTheme(_ theme: NSDictionary, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
32
- DispatchQueue.main.async {
33
- let dict = theme as? [String: Any] ?? [:]
34
- FrameRNTheme.current = dict.isEmpty ? nil : FrameRNTheme.parse(dict)
35
- resolve(nil)
33
+ func presentCheckout(from viewController: UIViewController, accountId: String?, amount: Int, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
34
+ guard let accountId, !accountId.isEmpty else {
35
+ reject("INVALID_ACCOUNT", "Frame.presentCheckout requires a non-empty accountId", nil)
36
+ return
36
37
  }
38
+ presentCheckoutOnMain(from: viewController, accountId: accountId, amount: amount, resolve: resolve, reject: reject)
37
39
  }
38
40
 
39
41
  @objc public
40
- func presentCheckout(from viewController: UIViewController, customerId: String?, amount: Int, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
41
- presentCheckoutOnMain(from: viewController, customerId: customerId, amount: amount, resolve: resolve, reject: reject)
42
- }
43
-
44
- @objc public
45
- func presentCart(from viewController: UIViewController, customerId: NSObject?, items: NSArray, shippingAmountInCents: Int, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
42
+ func presentCart(from viewController: UIViewController, accountId: NSObject?, items: NSArray, shippingAmountInCents: Int, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
46
43
  guard let cartItems = parseCartItems(items) else {
47
44
  reject("INVALID_ITEMS", "Invalid cart items array", nil)
48
45
  return
49
46
  }
50
- presentCartOnMain(from: viewController, customerId: customerId as? String, cartItems: cartItems, shippingAmountInCents: shippingAmountInCents, resolve: resolve, reject: reject)
47
+ guard let accountIdString = accountId as? String, !accountIdString.isEmpty else {
48
+ reject("INVALID_ACCOUNT", "Frame.presentCart requires a non-empty accountId", nil)
49
+ return
50
+ }
51
+ presentCartOnMain(from: viewController, accountId: accountIdString, cartItems: cartItems, shippingAmountInCents: shippingAmountInCents, resolve: resolve, reject: reject)
51
52
  }
52
53
 
53
54
  @objc public
@@ -62,10 +63,10 @@ public class FrameSDKBridge: NSObject {
62
63
  func presentApplePay(_ ownerType: String, ownerId: String, amount: Int, currency: String, merchantId: String, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
63
64
  DispatchQueue.main.async {
64
65
  Task { @MainActor in
65
- let owner: FrameApplePayViewModel.PaymentMethodOwner
66
+ let owner: ApplePayPresenter.Owner
66
67
  switch ownerType {
67
68
  case "customer": owner = .customer(ownerId)
68
- case "account": owner = .account(ownerId)
69
+ case "account": owner = .account(ownerId)
69
70
  default:
70
71
  reject("INVALID_OWNER", "owner.type must be 'customer' or 'account'", nil)
71
72
  return
@@ -104,25 +105,22 @@ public class FrameSDKBridge: NSObject {
104
105
 
105
106
  // MARK: - Private helpers
106
107
 
107
- private func presentCheckoutOnMain(from top: UIViewController, customerId: String?, amount: Int, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
108
+ private func presentCheckoutOnMain(from top: UIViewController, accountId: String, amount: Int, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
108
109
  var hosting: CheckoutHostingController!
109
- hosting = CheckoutHostingController(rootView: ThemedRoot(
110
- FrameCheckoutView(
111
- customerId: customerId,
112
- paymentAmount: amount,
113
- checkoutCallback: { [weak hosting] chargeIntent in
114
- hosting?.didComplete = true
115
- top.dismiss(animated: true)
116
- DispatchQueue.main.async {
117
- if let dict = Self.encodeChargeIntent(chargeIntent) {
118
- resolve(dict)
119
- } else {
120
- reject("ENCODE_ERROR", "Failed to encode charge intent", nil)
121
- }
110
+ hosting = CheckoutHostingController(rootView: FrameCheckoutView(
111
+ accountId: accountId,
112
+ paymentAmount: amount,
113
+ checkoutCallback: { [weak hosting] success, transferId in
114
+ hosting?.didComplete = true
115
+ top.dismiss(animated: true)
116
+ DispatchQueue.main.async {
117
+ if success, let transferId {
118
+ resolve(transferId)
119
+ } else {
120
+ reject("PAYMENT_FAILED", "Checkout did not produce a transfer id", nil)
122
121
  }
123
122
  }
124
- ),
125
- theme: FrameRNTheme.resolved()
123
+ }
126
124
  ))
127
125
  hosting.onCancel = {
128
126
  DispatchQueue.main.async {
@@ -138,11 +136,6 @@ public class FrameSDKBridge: NSObject {
138
136
  }
139
137
  }
140
138
 
141
- internal static func encodeChargeIntent(_ intent: FrameObjects.ChargeIntent) -> [String: Any]? {
142
- guard let data = try? JSONEncoder().encode(intent) else { return nil }
143
- return try? JSONSerialization.jsonObject(with: data) as? [String: Any]
144
- }
145
-
146
139
  private struct RNFrameCartItem: FrameCartItem {
147
140
  var id: String
148
141
  var imageURL: String
@@ -173,19 +166,29 @@ public class FrameSDKBridge: NSObject {
173
166
  return result
174
167
  }
175
168
 
176
- private func presentCartOnMain(from top: UIViewController, customerId: String?, cartItems: [RNFrameCartItem], shippingAmountInCents: Int, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
169
+ private func presentCartOnMain(from top: UIViewController, accountId: String, cartItems: [RNFrameCartItem], shippingAmountInCents: Int, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
170
+ // Single dismiss delegate guards against double-resolve: the inner checkout
171
+ // calls `finish(.success)` with the transfer id; bare-dismiss (swipe-down
172
+ // without completing checkout) calls `finish(.cancel)`.
173
+ let delegate = CartDismissDelegate(resolve: resolve, reject: reject)
177
174
  let cartView = FrameCartView(
178
- customer: nil,
175
+ accountId: accountId,
179
176
  cartItems: cartItems,
180
- shippingAmountInCents: shippingAmountInCents
177
+ shippingAmountInCents: shippingAmountInCents,
178
+ checkoutCallback: { [weak top, delegate] success, transferId in
179
+ if success, let transferId {
180
+ delegate.finish(.success(transferId))
181
+ } else {
182
+ delegate.finish(.cancel)
183
+ }
184
+ top?.dismiss(animated: true)
185
+ }
181
186
  )
182
- let hosting = UIHostingController(rootView: ThemedRoot(cartView, theme: FrameRNTheme.resolved()))
187
+ let hosting = UIHostingController(rootView: cartView)
183
188
  hosting.modalPresentationStyle = UIModalPresentationStyle.pageSheet
184
189
  if let sheet = hosting.sheetPresentationController {
185
190
  sheet.detents = [UISheetPresentationController.Detent.large()]
186
191
  }
187
- // When the sheet is dismissed (swipe or close), resolve. Note: FrameCartView does not expose ChargeIntent from nested checkout.
188
- let delegate = CartDismissDelegate(resolve: resolve)
189
192
  objc_setAssociatedObject(hosting, &cartDismissKey, delegate, .OBJC_ASSOCIATION_RETAIN)
190
193
  top.present(hosting, animated: true) {
191
194
  hosting.presentationController?.delegate = delegate
@@ -193,20 +196,22 @@ public class FrameSDKBridge: NSObject {
193
196
  }
194
197
 
195
198
  private func presentOnboardingOnMain(from top: UIViewController, accountId: String?, capabilities: [FrameObjects.Capabilities], applePayMerchantId: String?, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
196
- var hosting: OnboardingHostingController<ThemedRoot<OnboardingContainerView>>!
197
- var delegate: OnboardingDismissDelegate!
198
- hosting = OnboardingHostingController(
199
- rootView: ThemedRoot(
200
- OnboardingContainerView(
201
- accountId: accountId,
202
- requiredCapabilities: capabilities,
203
- applePayMerchantId: applePayMerchantId,
204
- onComplete: { [weak top] in
205
- delegate?.finish(completed: true)
206
- top?.dismiss(animated: true)
207
- }
208
- ),
209
- theme: FrameRNTheme.resolved()
199
+ // Build the dismiss delegate up-front so onComplete captures a non-nil
200
+ // instance directly. Earlier shape declared `var delegate: …!` and assigned
201
+ // it AFTER constructing OnboardingContainerView; the onComplete closure
202
+ // captured the local by reference, so any path that fired the callback
203
+ // before assignment landed on a nil delegate and silently no-op'd via `?.`.
204
+ let delegate = OnboardingDismissDelegate(resolve: resolve)
205
+
206
+ let hosting = OnboardingHostingController(
207
+ rootView: OnboardingContainerView(
208
+ accountId: accountId,
209
+ requiredCapabilities: capabilities,
210
+ applePayMerchantId: applePayMerchantId,
211
+ onComplete: { [delegate, weak top] in
212
+ delegate.finish(completed: true)
213
+ top?.dismiss(animated: true)
214
+ }
210
215
  )
211
216
  )
212
217
  // Embed in a UINavigationController so the outer sheet is a UIKit container,
@@ -222,7 +227,6 @@ public class FrameSDKBridge: NSObject {
222
227
  if let sheet = nav.sheetPresentationController {
223
228
  sheet.detents = [UISheetPresentationController.Detent.large()]
224
229
  }
225
- delegate = OnboardingDismissDelegate(resolve: resolve)
226
230
  delegate.hostingController = nav
227
231
  objc_setAssociatedObject(nav, &onboardingDismissKey, delegate, .OBJC_ASSOCIATION_RETAIN)
228
232
  NSLog("[FrameRN][onb] presenting OnboardingHostingController (wrapped in UINavigationController) from \(type(of: top))")
@@ -235,7 +239,7 @@ public class FrameSDKBridge: NSObject {
235
239
 
236
240
  // MARK: - CheckoutHostingController
237
241
 
238
- private final class CheckoutHostingController: UIHostingController<ThemedRoot<FrameCheckoutView>>, UIAdaptivePresentationControllerDelegate {
242
+ private final class CheckoutHostingController: UIHostingController<FrameCheckoutView>, UIAdaptivePresentationControllerDelegate {
239
243
  var didComplete = false
240
244
  var onCancel: (() -> Void)?
241
245
  private var cancelled = false
@@ -263,13 +267,34 @@ private final class OnboardingHostingController<V: View>: UIHostingController<V>
263
267
  // MARK: - Delegates
264
268
 
265
269
  private final class CartDismissDelegate: NSObject, UIAdaptivePresentationControllerDelegate {
266
- let resolve: RCTPromiseResolveBlock
267
- init(resolve: @escaping RCTPromiseResolveBlock) { self.resolve = resolve }
268
- func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
269
- DispatchQueue.main.async { [resolve] in
270
- resolve([String: Any]())
270
+ enum Outcome {
271
+ case success(String)
272
+ case cancel
273
+ }
274
+
275
+ private let resolve: RCTPromiseResolveBlock
276
+ private let reject: RCTPromiseRejectBlock
277
+ private var didFinish = false
278
+
279
+ init(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
280
+ self.resolve = resolve
281
+ self.reject = reject
282
+ }
283
+
284
+ func finish(_ outcome: Outcome) {
285
+ guard !didFinish else { return }
286
+ didFinish = true
287
+ DispatchQueue.main.async { [resolve, reject] in
288
+ switch outcome {
289
+ case .success(let transferId): resolve(transferId)
290
+ case .cancel: reject("USER_CANCELED", "User dismissed cart without completing checkout", nil)
291
+ }
271
292
  }
272
293
  }
294
+
295
+ func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
296
+ finish(.cancel)
297
+ }
273
298
  }
274
299
 
275
300
  private final class OnboardingDismissDelegate: NSObject, UIAdaptivePresentationControllerDelegate {
package/lib/errors.d.ts CHANGED
@@ -7,12 +7,20 @@ export declare const ErrorCodes: {
7
7
  readonly NO_ROOT_VC: "NO_ROOT_VC";
8
8
  readonly NO_ACTIVITY: "NO_ACTIVITY";
9
9
  readonly INVALID_ITEMS: "INVALID_ITEMS";
10
+ readonly INVALID_ACCOUNT: "INVALID_ACCOUNT";
11
+ readonly INVALID_OWNER: "INVALID_OWNER";
12
+ readonly INVALID_MERCHANT_ID: "INVALID_MERCHANT_ID";
13
+ readonly INVALID_AMOUNT: "INVALID_AMOUNT";
10
14
  readonly NETWORK_ERROR: "NETWORK_ERROR";
11
15
  readonly API_ERROR: "API_ERROR";
12
16
  readonly PARSE_ERROR: "PARSE_ERROR";
13
17
  readonly NO_RESULT: "NO_RESULT";
14
18
  readonly INIT_FAILED: "INIT_FAILED";
15
- readonly ENCODE_ERROR: "ENCODE_ERROR";
19
+ readonly APPLE_PAY_UNAVAILABLE: "APPLE_PAY_UNAVAILABLE";
20
+ readonly GOOGLE_PAY_UNAVAILABLE: "GOOGLE_PAY_UNAVAILABLE";
21
+ readonly NOT_ATTESTED: "NOT_ATTESTED";
22
+ readonly PAYMENT_METHOD_FAILED: "PAYMENT_METHOD_FAILED";
23
+ readonly PAYMENT_FAILED: "PAYMENT_FAILED";
16
24
  };
17
25
  export type FrameErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];
18
26
  export interface FrameErrorShape {
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,UAAU;;;;;;;;;;;;CAYb,CAAC;AAEX,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,OAAO,UAAU,CAAC,CAAC;AAE1E,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,eAAe,CASrE;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,OAAO,GAAG,eAAe,CAetE"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;CAoBb,CAAC;AAEX,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,OAAO,UAAU,CAAC,CAAC;AAE1E,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,eAAe,CASrE;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,OAAO,GAAG,eAAe,CAetE"}
package/lib/errors.js CHANGED
@@ -7,12 +7,20 @@ export const ErrorCodes = {
7
7
  NO_ROOT_VC: 'NO_ROOT_VC',
8
8
  NO_ACTIVITY: 'NO_ACTIVITY',
9
9
  INVALID_ITEMS: 'INVALID_ITEMS',
10
+ INVALID_ACCOUNT: 'INVALID_ACCOUNT',
11
+ INVALID_OWNER: 'INVALID_OWNER',
12
+ INVALID_MERCHANT_ID: 'INVALID_MERCHANT_ID',
13
+ INVALID_AMOUNT: 'INVALID_AMOUNT',
10
14
  NETWORK_ERROR: 'NETWORK_ERROR',
11
15
  API_ERROR: 'API_ERROR',
12
16
  PARSE_ERROR: 'PARSE_ERROR',
13
17
  NO_RESULT: 'NO_RESULT',
14
18
  INIT_FAILED: 'INIT_FAILED',
15
- ENCODE_ERROR: 'ENCODE_ERROR',
19
+ APPLE_PAY_UNAVAILABLE: 'APPLE_PAY_UNAVAILABLE',
20
+ GOOGLE_PAY_UNAVAILABLE: 'GOOGLE_PAY_UNAVAILABLE',
21
+ NOT_ATTESTED: 'NOT_ATTESTED',
22
+ PAYMENT_METHOD_FAILED: 'PAYMENT_METHOD_FAILED',
23
+ PAYMENT_FAILED: 'PAYMENT_FAILED',
16
24
  };
17
25
  export function isFrameError(error) {
18
26
  return (typeof error === 'object' &&
package/lib/index.d.ts CHANGED
@@ -7,12 +7,12 @@
7
7
  * - Use presentApplePay / presentGooglePay to launch the platform wallet sheet from your own button UI.
8
8
  * - For API calls (customers, charge intents, refunds), use the framepayments (frame-node) package from JS.
9
9
  */
10
- import { initialize, presentCheckout, presentCart, presentOnboarding, presentApplePay, presentGooglePay, setTheme } from './native';
11
- export { initialize, presentCheckout, presentCart, presentOnboarding, presentApplePay, presentGooglePay, setTheme, } from './native';
12
- export type { FrameCartItem, ChargeIntent, ChargeIntentStatus, AuthorizationMode, FrameError, BillingAddress, PaymentCard, BankAccount, PaymentMethod, OnboardingCapability, OnboardingResult, OnboardingResultStatus, ApplePayOwner, PresentApplePayOptions, PresentGooglePayOptions, FrameTheme, FrameThemeColor, FrameThemeFont, FrameThemeColors, FrameThemeFonts, FrameThemeRadii, } from './types';
10
+ import { initialize, presentCheckout, presentCart, presentOnboarding, presentApplePay, presentGooglePay } from './native';
11
+ export { initialize, presentCheckout, presentCart, presentOnboarding, presentApplePay, presentGooglePay, } from './native';
12
+ export type { FrameCartItem, FrameError, BillingAddress, PaymentCard, BankAccount, PaymentMethod, OnboardingCapability, OnboardingResult, OnboardingResultStatus, WalletOwner, ApplePayOwner, PresentApplePayOptions, PresentGooglePayOptions, FrameTheme, FrameThemeColor, FrameThemeFont, FrameThemeColors, FrameThemeFonts, FrameThemeRadii, } from './types';
13
13
  export { ErrorCodes } from './errors';
14
14
  export type { FrameErrorShape, FrameErrorCode } from './errors';
15
- /** Default export for Frame.initialize(), Frame.presentCheckout(), Frame.presentCart(), Frame.presentOnboarding(), Frame.presentApplePay(), Frame.presentGooglePay(), Frame.setTheme() */
15
+ /** Default export for Frame.initialize(), Frame.presentCheckout(), Frame.presentCart(), Frame.presentOnboarding(), Frame.presentApplePay(), Frame.presentGooglePay() */
16
16
  declare const _default: {
17
17
  initialize: typeof initialize;
18
18
  presentCheckout: typeof presentCheckout;
@@ -20,7 +20,6 @@ declare const _default: {
20
20
  presentOnboarding: typeof presentOnboarding;
21
21
  presentApplePay: typeof presentApplePay;
22
22
  presentGooglePay: typeof presentGooglePay;
23
- setTheme: typeof setTheme;
24
23
  };
25
24
  export default _default;
26
25
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,UAAU,EACV,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,QAAQ,EACT,MAAM,UAAU,CAAC;AAElB,OAAO,EACL,UAAU,EACV,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,QAAQ,GACT,MAAM,UAAU,CAAC;AAClB,YAAY,EACV,aAAa,EACb,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,UAAU,EACV,cAAc,EACd,WAAW,EACX,WAAW,EACX,aAAa,EACb,oBAAoB,EACpB,gBAAgB,EAChB,sBAAsB,EACtB,aAAa,EACb,sBAAsB,EACtB,uBAAuB,EACvB,UAAU,EACV,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,eAAe,GAChB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAEhE,0LAA0L;;;;;;;;;;AAC1L,wBAQE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,UAAU,EACV,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EACjB,MAAM,UAAU,CAAC;AAElB,OAAO,EACL,UAAU,EACV,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,eAAe,EACf,gBAAgB,GACjB,MAAM,UAAU,CAAC;AAClB,YAAY,EACV,aAAa,EACb,UAAU,EACV,cAAc,EACd,WAAW,EACX,WAAW,EACX,aAAa,EACb,oBAAoB,EACpB,gBAAgB,EAChB,sBAAsB,EACtB,WAAW,EACX,aAAa,EACb,sBAAsB,EACtB,uBAAuB,EACvB,UAAU,EACV,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,eAAe,GAChB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAEhE,wKAAwK;;;;;;;;;AACxK,wBAOE"}
package/lib/index.js CHANGED
@@ -7,10 +7,10 @@
7
7
  * - Use presentApplePay / presentGooglePay to launch the platform wallet sheet from your own button UI.
8
8
  * - For API calls (customers, charge intents, refunds), use the framepayments (frame-node) package from JS.
9
9
  */
10
- import { initialize, presentCheckout, presentCart, presentOnboarding, presentApplePay, presentGooglePay, setTheme, } from './native';
11
- export { initialize, presentCheckout, presentCart, presentOnboarding, presentApplePay, presentGooglePay, setTheme, } from './native';
10
+ import { initialize, presentCheckout, presentCart, presentOnboarding, presentApplePay, presentGooglePay, } from './native';
11
+ export { initialize, presentCheckout, presentCart, presentOnboarding, presentApplePay, presentGooglePay, } from './native';
12
12
  export { ErrorCodes } from './errors';
13
- /** Default export for Frame.initialize(), Frame.presentCheckout(), Frame.presentCart(), Frame.presentOnboarding(), Frame.presentApplePay(), Frame.presentGooglePay(), Frame.setTheme() */
13
+ /** Default export for Frame.initialize(), Frame.presentCheckout(), Frame.presentCart(), Frame.presentOnboarding(), Frame.presentApplePay(), Frame.presentGooglePay() */
14
14
  export default {
15
15
  initialize,
16
16
  presentCheckout,
@@ -18,5 +18,4 @@ export default {
18
18
  presentOnboarding,
19
19
  presentApplePay,
20
20
  presentGooglePay,
21
- setTheme,
22
21
  };
package/lib/native.d.ts CHANGED
@@ -1,36 +1,64 @@
1
1
  /**
2
2
  * Native module bridge. Uses NativeModules for classic React Native bridge.
3
3
  */
4
- import type { ChargeIntent, FrameCartItem, FrameTheme, OnboardingCapability, OnboardingResult, PresentApplePayOptions, PresentGooglePayOptions } from './types';
4
+ import type { FrameCartItem, FrameTheme, OnboardingCapability, OnboardingResult, PresentApplePayOptions, PresentGooglePayOptions } from './types';
5
5
  export declare function initialize(options: {
6
6
  secretKey: string;
7
7
  publishableKey: string;
8
8
  debugMode?: boolean;
9
+ /**
10
+ * Optional theme applied SDK-wide to Frame's reusable iOS components
11
+ * (checkout, cart, onboarding). Pass any subset — unspecified tokens fall
12
+ * back to SDK defaults. No-op on Android until frame-android ships a
13
+ * matching theme API.
14
+ */
15
+ theme?: FrameTheme;
9
16
  }): Promise<void>;
17
+ /**
18
+ * Presents the Frame checkout sheet for the given account. Resolves with the
19
+ * created Transfer's id string on success, or rejects with `USER_CANCELED` if
20
+ * the user dismisses the sheet.
21
+ *
22
+ * `accountId` is required: the bundled checkout creates a `Transfer`, which is
23
+ * account-scoped. Callers needing a customer/ChargeIntent flow should use
24
+ * `presentApplePay` / `presentGooglePay` directly with a customer owner.
25
+ */
10
26
  export declare function presentCheckout(options: {
11
- customerId?: string | null;
27
+ accountId: string;
12
28
  amount: number;
13
- }): Promise<ChargeIntent>;
29
+ }): Promise<string>;
30
+ /**
31
+ * Presents the Frame cart UI; tapping checkout routes through the same flow
32
+ * as `presentCheckout` and resolves with the created Transfer's id string.
33
+ *
34
+ * `accountId` is required for the same reason as `presentCheckout`.
35
+ */
14
36
  export declare function presentCart(options: {
15
- customerId?: string | null;
37
+ accountId: string;
16
38
  items: FrameCartItem[];
17
39
  shippingAmountInCents: number;
18
- }): Promise<ChargeIntent>;
40
+ }): Promise<string>;
19
41
  export declare function presentOnboarding(options: {
20
42
  accountId?: string | null;
21
43
  capabilities?: OnboardingCapability[];
22
44
  applePayMerchantId?: string | null;
23
45
  googlePayMerchantId?: string | null;
24
46
  }): Promise<OnboardingResult>;
25
- export declare function presentApplePay(options: PresentApplePayOptions): Promise<ChargeIntent>;
26
- export declare function presentGooglePay(options: PresentGooglePayOptions): Promise<ChargeIntent>;
27
47
  /**
28
- * Configure colors, fonts, and corner radii for Frame's reusable iOS
29
- * components. Applied to every subsequent `present*` call; an in-flight modal
30
- * is not re-themed mid-flow.
48
+ * Presents the Apple Pay sheet and creates a charge from the resulting wallet
49
+ * payment method. Resolves with the created resource's id string on success,
50
+ * or rejects with `USER_CANCELED` if the sheet is dismissed.
51
+ *
52
+ * - `owner.type === 'customer'` → creates a `ChargeIntent`; resolves with its id.
53
+ * - `owner.type === 'account'` → creates a `Transfer`; resolves with its id.
54
+ */
55
+ export declare function presentApplePay(options: PresentApplePayOptions): Promise<string>;
56
+ /**
57
+ * Presents Google Pay and creates a charge from the resulting wallet payment method.
58
+ * Resolves with the created resource's id string on success.
31
59
  *
32
- * Pass `null` or `{}` to reset to SDK defaults. Android is a no-op until
33
- * frame-android ships a matching theme API.
60
+ * - `owner.type === 'customer'` creates a `ChargeIntent`; resolves with its id.
61
+ * - `owner.type === 'account'` → creates a `Transfer`; resolves with its id.
34
62
  */
35
- export declare function setTheme(theme: FrameTheme | null): Promise<void>;
63
+ export declare function presentGooglePay(options: PresentGooglePayOptions): Promise<string>;
36
64
  //# sourceMappingURL=native.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../src/native.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,UAAU,EACV,oBAAoB,EACpB,gBAAgB,EAChB,sBAAsB,EACtB,uBAAuB,EACxB,MAAM,SAAS,CAAC;AAmBjB,wBAAgB,UAAU,CAAC,OAAO,EAAE;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBhB;AAwBD,wBAAgB,eAAe,CAAC,OAAO,EAAE;IACvC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,YAAY,CAAC,CAKxB;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE;IACnC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,qBAAqB,EAAE,MAAM,CAAC;CAC/B,GAAG,OAAO,CAAC,YAAY,CAAC,CASxB;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IACzC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACtC,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAkB5B;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,YAAY,CAAC,CAoBtF;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,YAAY,CAAC,CAUxF;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAMhE"}
1
+ {"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../src/native.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EACV,aAAa,EACb,UAAU,EACV,oBAAoB,EACpB,gBAAgB,EAChB,sBAAsB,EACtB,uBAAuB,EACxB,MAAM,SAAS,CAAC;AAiCjB,wBAAgB,UAAU,CAAC,OAAO,EAAE;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,UAAU,CAAC;CACpB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBhB;AAwBD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAQlB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,qBAAqB,EAAE,MAAM,CAAC;CAC/B,GAAG,OAAO,CAAC,MAAM,CAAC,CAYlB;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IACzC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACtC,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAkB5B;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,CAoBhF;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBlF"}
package/lib/native.js CHANGED
@@ -3,6 +3,18 @@
3
3
  */
4
4
  import { NativeModules, Platform } from 'react-native';
5
5
  import { ErrorCodes } from './errors';
6
+ /**
7
+ * Throw a coded error from synchronous JS validation. Mirrors the `code`/`message`
8
+ * shape that native rejections produce so consumers can catch `e.code === 'INVALID_*'`
9
+ * uniformly.
10
+ */
11
+ function throwCoded(code, message) {
12
+ const err = new Error(message);
13
+ err.code = code;
14
+ throw err;
15
+ }
16
+ // theme is iOS-only today: frame-android does not yet have a matching theme API,
17
+ // so the field is accepted on both platforms but ignored on Android until it does.
6
18
  const LINKING_ERROR = `The package 'framepayments-react-native' doesn't seem to be linked. Make sure you have run 'pod install' (iOS) or rebuilt the app (Android).`;
7
19
  const FrameSDK = NativeModules.FrameSDK
8
20
  ? NativeModules.FrameSDK
@@ -14,12 +26,15 @@ const FrameSDK = NativeModules.FrameSDK
14
26
  let isInitialized = false;
15
27
  export function initialize(options) {
16
28
  if (!options?.secretKey) {
17
- throw new Error('Frame.initialize requires secretKey');
29
+ throwCoded(ErrorCodes.INIT_FAILED, 'Frame.initialize requires secretKey');
18
30
  }
19
31
  if (!options?.publishableKey) {
20
- throw new Error('Frame.initialize requires publishableKey');
32
+ throwCoded(ErrorCodes.INIT_FAILED, 'Frame.initialize requires publishableKey');
21
33
  }
22
- return wrapPromise(FrameSDK.initialize(options.secretKey, options.publishableKey, options.debugMode ?? false)).then(() => {
34
+ if (options.theme !== undefined && (typeof options.theme !== 'object' || Array.isArray(options.theme))) {
35
+ throwCoded(ErrorCodes.INIT_FAILED, 'Frame.initialize: theme must be an object');
36
+ }
37
+ return wrapPromise(FrameSDK.initialize(options.secretKey, options.publishableKey, options.debugMode ?? false, options.theme ?? null)).then(() => {
23
38
  isInitialized = true;
24
39
  });
25
40
  }
@@ -43,13 +58,34 @@ function wrapPromise(p) {
43
58
  throw Object.assign(new Error(message), { code, message });
44
59
  });
45
60
  }
61
+ /**
62
+ * Presents the Frame checkout sheet for the given account. Resolves with the
63
+ * created Transfer's id string on success, or rejects with `USER_CANCELED` if
64
+ * the user dismisses the sheet.
65
+ *
66
+ * `accountId` is required: the bundled checkout creates a `Transfer`, which is
67
+ * account-scoped. Callers needing a customer/ChargeIntent flow should use
68
+ * `presentApplePay` / `presentGooglePay` directly with a customer owner.
69
+ */
46
70
  export function presentCheckout(options) {
47
71
  guardInitialized();
48
- return wrapPromise(FrameSDK.presentCheckout(options.customerId ?? null, options.amount));
72
+ if (!options?.accountId) {
73
+ throwCoded(ErrorCodes.INVALID_ACCOUNT, 'Frame.presentCheckout requires accountId');
74
+ }
75
+ return wrapPromise(FrameSDK.presentCheckout(options.accountId, options.amount));
49
76
  }
77
+ /**
78
+ * Presents the Frame cart UI; tapping checkout routes through the same flow
79
+ * as `presentCheckout` and resolves with the created Transfer's id string.
80
+ *
81
+ * `accountId` is required for the same reason as `presentCheckout`.
82
+ */
50
83
  export function presentCart(options) {
51
84
  guardInitialized();
52
- return wrapPromise(FrameSDK.presentCart(options.customerId ?? null, options.items, options.shippingAmountInCents));
85
+ if (!options?.accountId) {
86
+ throwCoded(ErrorCodes.INVALID_ACCOUNT, 'Frame.presentCart requires accountId');
87
+ }
88
+ return wrapPromise(FrameSDK.presentCart(options.accountId, options.items, options.shippingAmountInCents));
53
89
  }
54
90
  export function presentOnboarding(options) {
55
91
  guardInitialized();
@@ -58,36 +94,41 @@ export function presentOnboarding(options) {
58
94
  }
59
95
  return wrapPromise(FrameSDK.presentOnboarding(options.accountId ?? null, options.capabilities ?? [], options.googlePayMerchantId ?? null));
60
96
  }
97
+ /**
98
+ * Presents the Apple Pay sheet and creates a charge from the resulting wallet
99
+ * payment method. Resolves with the created resource's id string on success,
100
+ * or rejects with `USER_CANCELED` if the sheet is dismissed.
101
+ *
102
+ * - `owner.type === 'customer'` → creates a `ChargeIntent`; resolves with its id.
103
+ * - `owner.type === 'account'` → creates a `Transfer`; resolves with its id.
104
+ */
61
105
  export function presentApplePay(options) {
62
106
  guardInitialized();
63
107
  if (!options?.owner || (options.owner.type !== 'customer' && options.owner.type !== 'account')) {
64
- throw new Error('Frame.presentApplePay requires owner: { type: "customer" | "account", id: string }');
108
+ throwCoded(ErrorCodes.INVALID_OWNER, 'Frame.presentApplePay requires owner: { type: "customer" | "account", id: string }');
65
109
  }
66
110
  if (!options.owner.id) {
67
- throw new Error('Frame.presentApplePay requires owner.id');
111
+ throwCoded(ErrorCodes.INVALID_OWNER, 'Frame.presentApplePay requires owner.id');
68
112
  }
69
113
  if (!options.merchantId) {
70
- throw new Error('Frame.presentApplePay requires merchantId');
114
+ throwCoded(ErrorCodes.INVALID_MERCHANT_ID, 'Frame.presentApplePay requires merchantId');
71
115
  }
72
116
  return wrapPromise(FrameSDK.presentApplePay(options.owner.type, options.owner.id, options.amount, options.currency ?? 'usd', options.merchantId));
73
117
  }
74
- export function presentGooglePay(options) {
75
- guardInitialized();
76
- return wrapPromise(FrameSDK.presentGooglePay(options.amountCents, options.customerId ?? null, options.currencyCode ?? 'USD', options.googlePayMerchantId ?? null));
77
- }
78
118
  /**
79
- * Configure colors, fonts, and corner radii for Frame's reusable iOS
80
- * components. Applied to every subsequent `present*` call; an in-flight modal
81
- * is not re-themed mid-flow.
119
+ * Presents Google Pay and creates a charge from the resulting wallet payment method.
120
+ * Resolves with the created resource's id string on success.
82
121
  *
83
- * Pass `null` or `{}` to reset to SDK defaults. Android is a no-op until
84
- * frame-android ships a matching theme API.
122
+ * - `owner.type === 'customer'` creates a `ChargeIntent`; resolves with its id.
123
+ * - `owner.type === 'account'` → creates a `Transfer`; resolves with its id.
85
124
  */
86
- export function setTheme(theme) {
87
- if (theme !== null && (typeof theme !== 'object' || Array.isArray(theme))) {
88
- throw new Error('Frame.setTheme requires a theme object or null');
125
+ export function presentGooglePay(options) {
126
+ guardInitialized();
127
+ if (!options?.owner || (options.owner.type !== 'customer' && options.owner.type !== 'account')) {
128
+ throwCoded(ErrorCodes.INVALID_OWNER, 'Frame.presentGooglePay requires owner: { type: "customer" | "account", id: string }');
129
+ }
130
+ if (!options.owner.id) {
131
+ throwCoded(ErrorCodes.INVALID_OWNER, 'Frame.presentGooglePay requires owner.id');
89
132
  }
90
- if (Platform.OS !== 'ios')
91
- return Promise.resolve();
92
- return wrapPromise(FrameSDK.setTheme(theme ?? {}));
133
+ return wrapPromise(FrameSDK.presentGooglePay(options.amountCents, options.owner.type, options.owner.id, options.currencyCode ?? 'USD', options.googlePayMerchantId ?? null));
93
134
  }