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
package/README.md CHANGED
@@ -72,11 +72,12 @@ await Frame.initialize({
72
72
  debugMode: __DEV__,
73
73
  });
74
74
 
75
- // 2. Present a checkout modal
76
- const chargeIntent = await Frame.presentCheckout({ amount: 10000 }); // cents
75
+ // 2. Present a checkout modal — resolves with the transfer id string
76
+ const transferId = await Frame.presentCheckout({ amount: 10000, accountId: 'acct_xxx' });
77
77
 
78
- // 3. Present a cart flow
79
- const result = await Frame.presentCart({
78
+ // 3. Present a cart flow — also resolves with the transfer id string
79
+ const transferId2 = await Frame.presentCart({
80
+ accountId: 'acct_xxx',
80
81
  items: [{ id: '1', title: 'Hat', amountInCents: 5000, imageUrl: 'https://...' }],
81
82
  shippingAmountInCents: 500,
82
83
  });
@@ -114,30 +115,35 @@ await Frame.initialize({
114
115
 
115
116
  ### `Frame.presentCheckout(options)`
116
117
 
117
- Opens the native checkout modal. Resolves with a `ChargeIntent` when the user completes payment.
118
+ Opens the native checkout modal. Resolves with the created Transfer's id string when the user completes payment. Rejects with `USER_CANCELED` if the sheet is dismissed.
119
+
120
+ `accountId` is **required**: the bundled checkout creates a `Transfer`, which is account-scoped. If you need a customer/ChargeIntent flow, render your own UI and call `presentApplePay` / `presentGooglePay` directly with a customer owner instead.
118
121
 
119
122
  ```ts
120
- const chargeIntent = await Frame.presentCheckout({
121
- amount: 15000, // required, in cents
122
- customerId: 'cus_xxx', // optional
123
+ const transferId = await Frame.presentCheckout({
124
+ accountId: 'acct_xxx',
125
+ amount: 15000, // in cents
123
126
  });
124
127
  ```
125
128
 
126
129
  | Option | Type | Required | Description |
127
130
  |---|---|---|---|
131
+ | `accountId` | `string` | Yes | Frame account that the resulting Transfer is created against |
128
132
  | `amount` | `number` | Yes | Payment amount in cents |
129
- | `customerId` | `string` | No | Pre-associate the charge with a Frame customer |
130
133
 
131
- **Returns:** [`ChargeIntent`](#chargeintent)
134
+ **Returns:** `Promise<string>` — the created Transfer's `id`.
135
+
136
+ **Throws synchronously with `code: 'INVALID_ACCOUNT'`** if `accountId` is missing or empty.
132
137
 
133
138
  ---
134
139
 
135
140
  ### `Frame.presentCart(options)`
136
141
 
137
- Opens a cart review screen followed by the checkout flow. Resolves when the user completes payment or dismisses.
142
+ Opens a cart review screen followed by the checkout flow. Routes through the same checkout path as `presentCheckout`, so it requires the same `accountId` and resolves with the created Transfer's id string.
138
143
 
139
144
  ```ts
140
- const chargeIntent = await Frame.presentCart({
145
+ const transferId = await Frame.presentCart({
146
+ accountId: 'acct_xxx',
141
147
  items: [
142
148
  {
143
149
  id: '1',
@@ -147,15 +153,16 @@ const chargeIntent = await Frame.presentCart({
147
153
  },
148
154
  ],
149
155
  shippingAmountInCents: 500,
150
- customerId: 'cus_xxx', // optional
151
156
  });
152
157
  ```
153
158
 
154
159
  | Option | Type | Required | Description |
155
160
  |---|---|---|---|
161
+ | `accountId` | `string` | Yes | Frame account that the resulting Transfer is created against |
156
162
  | `items` | `FrameCartItem[]` | Yes | Array of items to display in the cart |
157
163
  | `shippingAmountInCents` | `number` | Yes | Shipping cost in cents |
158
- | `customerId` | `string` | No | Pre-associate the charge with a Frame customer |
164
+
165
+ **Returns:** `Promise<string>` — the created Transfer's `id`.
159
166
 
160
167
  **`FrameCartItem` shape:**
161
168
 
@@ -166,10 +173,6 @@ const chargeIntent = await Frame.presentCart({
166
173
  | `amountInCents` | `number` | Item price in cents |
167
174
  | `imageUrl` | `string` | URL of the product image |
168
175
 
169
- **Returns:** [`ChargeIntent`](#chargeintent)
170
-
171
- > **iOS limitation:** On iOS, `presentCart` resolves with an empty object (`{}`) rather than a full `ChargeIntent`. The underlying `FrameCartView` does not expose the charge intent from its nested checkout step. On Android, the full `ChargeIntent` is returned. Always guard with `intent?.id` before using the result.
172
-
173
176
  ---
174
177
 
175
178
  ### `Frame.presentOnboarding(options)`
@@ -222,28 +225,45 @@ if (result.status === 'completed') {
222
225
 
223
226
  ### `Frame.presentApplePay(options)` (iOS)
224
227
 
225
- Launches the native Apple Pay sheet, creates a Frame payment method from the authorized payment, and creates and confirms a charge intent. Resolves with the resulting `ChargeIntent`. Render your own button — Apple's `PKPaymentButton`, a community wrapper, or your own design-system component — and call this from its `onPress`.
228
+ Launches the native Apple Pay sheet, creates a Frame payment method from the authorized payment, and creates a charge against the owner. Resolves with the resulting resource's id string. Render your own button — Apple's `PKPaymentButton`, a community wrapper, or your own design-system component — and call this from its `onPress`.
229
+
230
+ The `owner` determines which downstream resource is created:
231
+
232
+ - `owner.type === 'customer'` → creates a `ChargeIntent` against the customer; resolves with the ChargeIntent's `id`.
233
+ - `owner.type === 'account'` → creates a `Transfer` charged into the account; resolves with the Transfer's `id`.
234
+
235
+ In both cases the resolved value is a `string`; the caller knows which resource the id refers to based on the owner passed in.
226
236
 
227
237
  ```tsx
228
238
  import Frame from 'framepayments-react-native';
229
239
 
230
- const intent = await Frame.presentApplePay({
240
+ // Account Transfer
241
+ const transferId = await Frame.presentApplePay({
242
+ amount: 15000,
243
+ currency: 'usd',
244
+ owner: { type: 'account', id: 'acct_xxx' },
245
+ merchantId: 'merchant.com.yourapp',
246
+ });
247
+
248
+ // Customer → ChargeIntent
249
+ const chargeIntentId = await Frame.presentApplePay({
231
250
  amount: 15000,
232
251
  currency: 'usd',
233
252
  owner: { type: 'customer', id: 'cus_xxx' },
234
253
  merchantId: 'merchant.com.yourapp',
235
254
  });
236
- console.log('Charge intent:', intent.id);
237
255
  ```
238
256
 
239
257
  | Option | Type | Required | Description |
240
258
  |---|---|---|---|
241
259
  | `amount` | `number` | Yes | Payment amount in cents |
242
260
  | `currency` | `string` | No | ISO 4217 currency code. Default `'usd'` |
243
- | `owner` | `{ type: 'customer' \| 'account', id: string }` | Yes | Frame customer or account that owns the resulting payment method |
261
+ | `owner` | `{ type: 'customer' \| 'account', id: string }` | Yes | Customer or account that owns the resulting payment method and charge |
244
262
  | `merchantId` | `string` | Yes | Apple Pay merchant ID configured in your Apple Developer account |
245
263
 
246
- The promise rejects with `code: 'USER_CANCELED'` when the user dismisses the sheet, `'APPLE_PAY_UNAVAILABLE'` if the device cannot make Apple Pay payments, `'NOT_ATTESTED'` if device attestation has not completed yet (try again in a moment), and `'PAYMENT_METHOD_FAILED'` / `'CHARGE_INTENT_FAILED'` for backend failures.
264
+ **Returns:** `Promise<string>` the created `ChargeIntent`'s `id` (for customer owners) or the `Transfer`'s `id` (for account owners).
265
+
266
+ The promise rejects with `code: 'USER_CANCELED'` when the user dismisses the sheet, `'INVALID_OWNER'` if the owner is missing or malformed, `'APPLE_PAY_UNAVAILABLE'` if the device cannot make Apple Pay payments, `'NOT_ATTESTED'` if device attestation has not completed yet (try again in a moment), `'PAYMENT_METHOD_FAILED'` when the wallet payment method could not be persisted, and `'PAYMENT_FAILED'` when the downstream ChargeIntent or Transfer could not be created.
247
267
 
248
268
  **Required iOS setup:**
249
269
 
@@ -263,27 +283,40 @@ On non-iOS platforms `Frame.presentApplePay` rejects synchronously with a not-su
263
283
 
264
284
  ### `Frame.presentGooglePay(options)` (Android)
265
285
 
266
- Launches the native Google Pay sheet, creates a Frame payment method from the wallet token, and creates and confirms a charge intent. Resolves with the resulting `ChargeIntent`. Render your own button (Google's `PayButton` from `play-services-pay`, a community wrapper, or your own component) and call this from its `onPress`.
286
+ Launches the native Google Pay sheet, creates a Frame payment method from the wallet token, and creates a charge against the owner. Resolves with the resulting resource's id string. Render your own button (Google's `PayButton` from `play-services-pay`, a community wrapper, or your own component) and call this from its `onPress`.
287
+
288
+ The `owner` mirrors `presentApplePay` and determines which downstream resource is created:
289
+
290
+ - `owner.type === 'customer'` → creates a `ChargeIntent` against the customer; resolves with the ChargeIntent's `id`.
291
+ - `owner.type === 'account'` → creates a `Transfer` charged into the account; resolves with the Transfer's `id`.
267
292
 
268
293
  ```tsx
269
294
  import Frame from 'framepayments-react-native';
270
295
 
271
- const intent = await Frame.presentGooglePay({
296
+ // Account Transfer
297
+ const transferId = await Frame.presentGooglePay({
272
298
  amountCents: 15000,
273
299
  currencyCode: 'USD',
274
- customerId: 'cus_xxx',
300
+ owner: { type: 'account', id: 'acct_xxx' },
301
+ });
302
+
303
+ // Customer → ChargeIntent
304
+ const chargeIntentId = await Frame.presentGooglePay({
305
+ amountCents: 15000,
306
+ owner: { type: 'customer', id: 'cus_xxx' },
275
307
  });
276
- console.log('Charge intent:', intent.id);
277
308
  ```
278
309
 
279
310
  | Option | Type | Required | Description |
280
311
  |---|---|---|---|
281
312
  | `amountCents` | `number` | Yes | Payment amount in cents |
282
- | `customerId` | `string` | No | Frame customer to associate the payment method with |
313
+ | `owner` | `{ type: 'customer' \| 'account', id: string }` | Yes | Customer or account that owns the resulting payment method and charge |
283
314
  | `currencyCode` | `string` | No | ISO 4217 currency code. Default `'USD'` |
284
315
  | `googlePayMerchantId` | `string` | No | Google Pay merchant ID override |
285
316
 
286
- The promise rejects with `code: 'USER_CANCELED'` when the user dismisses the sheet, `'GOOGLE_PAY_UNAVAILABLE'` if Google Pay is not ready on the device (no signed-in account, no test card, or Wallet API disabled), and `'PAYMENT_FAILED'` for backend failures.
317
+ **Returns:** `Promise<string>` the created `ChargeIntent`'s `id` (for customer owners) or the `Transfer`'s `id` (for account owners).
318
+
319
+ The promise rejects with `code: 'USER_CANCELED'` when the user dismisses the sheet, `'INVALID_OWNER'` if the owner is missing or malformed, `'GOOGLE_PAY_UNAVAILABLE'` if Google Pay is not ready on the device (no signed-in account, no test card, or Wallet API disabled), and `'PAYMENT_FAILED'` for backend failures.
287
320
 
288
321
  **Required Android setup:**
289
322
 
@@ -299,32 +332,37 @@ On non-Android platforms `Frame.presentGooglePay` rejects synchronously with a n
299
332
 
300
333
  ---
301
334
 
302
- ### `Frame.setTheme(theme)` (iOS)
335
+ ### Theming (iOS)
303
336
 
304
337
  Customizes colors, fonts, and corner radii on Frame's reusable components — checkout, cart, and the onboarding flow. Backed by `FrameTheme` introduced in Frame-iOS 2.1.2.
305
338
 
306
- Call once at app startup (after `Frame.initialize`). The theme applies to every subsequent `present*` call. Modals already on screen are not re-themed mid-flow. Pass `null` or `{}` to reset to defaults; pass a partial dict to override only specific tokens.
339
+ Pass an optional `theme` to `Frame.initialize`. It's stored on `FrameNetworking.shared` and read by every Frame view at present time, so all subsequent `present*` calls render with it. Modals already on screen are not re-themed if the theme is changed mid-flow. Omit the field, or pass `{}`, to use SDK defaults; pass a partial dict to override only specific tokens.
307
340
 
308
341
  ```ts
309
342
  import Frame from 'framepayments-react-native';
310
343
 
311
- await Frame.setTheme({
312
- colors: {
313
- primaryButton: '#5B2DFF',
314
- primaryButtonText: '#FFFFFF',
315
- surface: '#0A0A0A',
316
- textPrimary: '#FFFFFF',
317
- error: '#E53935',
318
- },
319
- fonts: {
320
- title: { name: 'Inter-Bold', size: 24 },
321
- button: { name: 'Inter-SemiBold', size: 16 },
344
+ await Frame.initialize({
345
+ secretKey: 'sk_sandbox_...',
346
+ publishableKey: 'pk_sandbox_...',
347
+ debugMode: __DEV__,
348
+ theme: {
349
+ colors: {
350
+ primaryButton: '#5B2DFF',
351
+ primaryButtonText: '#FFFFFF',
352
+ surface: '#0A0A0A',
353
+ textPrimary: '#FFFFFF',
354
+ error: '#E53935',
355
+ },
356
+ fonts: {
357
+ title: { name: 'Inter-Bold', size: 24 },
358
+ button: { name: 'Inter-SemiBold', size: 16 },
359
+ },
360
+ radii: { medium: 16 },
322
361
  },
323
- radii: { medium: 16 },
324
362
  });
325
363
  ```
326
364
 
327
- **Android**: `setTheme()` resolves immediately and has no effect — `frame-android` does not yet have a matching theme API.
365
+ **Android**: the `theme` field is accepted for cross-platform parity but currently has no effect — `frame-android` does not yet have a matching theme API.
328
366
 
329
367
  #### Tokens
330
368
 
@@ -387,7 +425,7 @@ Apple and Google both require their official button artwork (with light/dark var
387
425
  import { Image, Platform, TouchableOpacity, useColorScheme } from 'react-native';
388
426
  import Frame from 'framepayments-react-native';
389
427
 
390
- export function WalletButton({ amountCents, customerId, merchantId }) {
428
+ export function WalletButton({ amountCents, accountId, merchantId }) {
391
429
  const colorScheme = useColorScheme();
392
430
  const isDark = colorScheme === 'dark';
393
431
 
@@ -397,11 +435,14 @@ export function WalletButton({ amountCents, customerId, merchantId }) {
397
435
  await Frame.presentApplePay({
398
436
  amount: amountCents,
399
437
  currency: 'usd',
400
- owner: { type: 'customer', id: customerId },
438
+ owner: { type: 'account', id: accountId },
401
439
  merchantId,
402
440
  });
403
441
  } else {
404
- await Frame.presentGooglePay({ amountCents, customerId });
442
+ await Frame.presentGooglePay({
443
+ amountCents,
444
+ owner: { type: 'account', id: accountId },
445
+ });
405
446
  }
406
447
  } catch (e: any) {
407
448
  if (e.code === 'USER_CANCELED') return;
@@ -429,27 +470,9 @@ A complete working example (including loading-state handling) lives in [example/
429
470
 
430
471
  ---
431
472
 
432
- ### `ChargeIntent`
473
+ ### Inspecting the full resource
433
474
 
434
- Returned from `presentCheckout` and `presentCart` (Android only for cart).
435
-
436
- | Field | Type | Description |
437
- |---|---|---|
438
- | `id` | `string` | Unique charge intent ID |
439
- | `amount` | `number` | Amount in cents |
440
- | `currency` | `string` | ISO currency code (e.g. `"usd"`) |
441
- | `status` | `ChargeIntentStatus` | Current status of the intent |
442
- | `created` | `number` | Unix timestamp |
443
- | `updated` | `number` | Unix timestamp |
444
- | `livemode` | `boolean` | `true` in production, `false` in sandbox |
445
- | `description` | `string \| undefined` | Optional description |
446
- | `authorizationMode` | `'automatic' \| 'manual' \| undefined` | Capture mode |
447
- | `failureDescription` | `string \| undefined` | Present when status is `failed` |
448
- | `customer` | `Customer \| undefined` | Associated customer object |
449
- | `paymentMethod` | `PaymentMethod \| undefined` | Payment method used |
450
- | `latestCharge` | `Charge \| undefined` | Most recent charge on this intent |
451
-
452
- **`ChargeIntentStatus` values:** `pending`, `succeeded`, `failed`, `canceled`, `incomplete`, `disputed`, `refunded`, `reversed`
475
+ The `present*` flows resolve with a string id only. If you need the full `Transfer` or `ChargeIntent` object after a checkout completes, fetch it server-side from the Frame API using the returned id — see [https://docs.framepayments.com/frameos/transfers](https://docs.framepayments.com/frameos/transfers) and the corresponding ChargeIntent docs for the response schemas. (This SDK doesn't ship TypeScript types for those objects; use the [`framepayments`](https://www.npmjs.com/package/framepayments) Node package if you want typed access from JS.)
453
476
 
454
477
  ---
455
478
 
@@ -461,7 +484,7 @@ All `present*` methods return Promises that reject with an error object containi
461
484
  import Frame, { ErrorCodes } from 'framepayments-react-native';
462
485
 
463
486
  try {
464
- const intent = await Frame.presentCheckout({ amount: 10000 });
487
+ const transferId = await Frame.presentCheckout({ amount: 10000, accountId: 'acct_xxx' });
465
488
  // handle success
466
489
  } catch (e: any) {
467
490
  if (e.code === ErrorCodes.USER_CANCELED) {
@@ -481,9 +504,17 @@ try {
481
504
  | `NO_ROOT_VC` | iOS: no root view controller available |
482
505
  | `NO_ACTIVITY` | Android: no host activity available |
483
506
  | `INVALID_ITEMS` | Cart items could not be parsed |
507
+ | `INVALID_ACCOUNT` | `accountId` was missing or empty (presentCheckout, presentCart) |
508
+ | `INVALID_OWNER` | Apple Pay / Google Pay `owner` was missing, malformed, or had an empty `id` |
509
+ | `INVALID_MERCHANT_ID` | Apple Pay `merchantId` was missing or empty |
510
+ | `INVALID_AMOUNT` | Google Pay `amountCents` was missing or non-positive |
484
511
  | `NO_RESULT` | Native activity returned OK but no payload |
485
512
  | `PARSE_ERROR` | Could not decode the native response |
486
- | `ENCODE_ERROR` | iOS: could not encode the charge intent |
513
+ | `APPLE_PAY_UNAVAILABLE` | iOS: device cannot make Apple Pay payments |
514
+ | `GOOGLE_PAY_UNAVAILABLE` | Android: Google Pay not ready on the device |
515
+ | `NOT_ATTESTED` | iOS: device attestation has not completed yet |
516
+ | `PAYMENT_METHOD_FAILED` | iOS: Apple Pay payment method creation failed |
517
+ | `PAYMENT_FAILED` | Wallet flow failed during Transfer creation |
487
518
  | `NETWORK_ERROR` | Network failure in the native SDK |
488
519
  | `API_ERROR` | Frame API returned an error |
489
520
 
@@ -493,7 +524,7 @@ You can also use the `isFrameError` and `normalizeToFrameError` utilities for ty
493
524
  import { isFrameError, normalizeToFrameError } from 'framepayments-react-native';
494
525
 
495
526
  try {
496
- await Frame.presentCheckout({ amount: 5000 });
527
+ await Frame.presentCheckout({ accountId: 'acct_xxx', amount: 5000 });
497
528
  } catch (e) {
498
529
  const err = normalizeToFrameError(e);
499
530
  // err.code, err.message, err.nativeError are all typed strings
@@ -557,10 +588,6 @@ Also ensure the **Frame-iOS** Swift package is added in Xcode (**File → Add Pa
557
588
 
558
589
  Ensure you are using SDK version 1.1.0+. Earlier versions had a bug where programmatic dismiss from the onboarding flow did not resolve the promise.
559
590
 
560
- ### `presentCart` returns `{}` on iOS
561
-
562
- This is a known limitation of `FrameCartView` on iOS — it does not expose the `ChargeIntent` from its nested checkout. On Android, the full object is returned. Guard with `intent?.id` before reading the result.
563
-
564
591
  ### `App ID verification failed` from `presentApplePay`
565
592
 
566
593
  The Frame backend computes `SHA256("<TeamID>.<BundleID>")` from the merchant's dashboard configuration and compares it to the hash signed by the device during attestation. A mismatch returns `App ID verification failed`. Fix: open your Frame dashboard → **Settings → Device Attestation** and confirm both the Apple Team ID and the Bundle ID match the iOS app you're running.
@@ -1 +1 @@
1
- #Fri May 01 16:00:34 PDT 2026
1
+ #Mon May 11 22:24:08 PDT 2026
@@ -31,9 +31,9 @@ android {
31
31
  dependencies {
32
32
  implementation 'com.facebook.react:react-native:+'
33
33
  implementation "org.jetbrains.kotlin:kotlin-stdlib:2.1.0"
34
- implementation 'com.framepayments:framesdk:2.0.4'
35
- implementation 'com.framepayments:framesdk_ui:2.0.4'
36
- implementation 'com.framepayments:framesdk_onboarding:2.0.4'
34
+ implementation 'com.framepayments:framesdk:2.0.6'
35
+ implementation 'com.framepayments:framesdk_ui:2.0.6'
36
+ implementation 'com.framepayments:framesdk_onboarding:2.0.6'
37
37
  // Required by FrameGooglePayButton (PaymentsClient, WalletConstants).
38
38
  // framesdk_ui declares this as `implementation`, so it is not exposed transitively.
39
39
  implementation 'com.google.android.gms:play-services-wallet:19.4.0'
@@ -7,9 +7,7 @@ import android.os.Looper
7
7
  import android.widget.FrameLayout
8
8
  import androidx.appcompat.app.AppCompatActivity
9
9
  import com.framepayments.framesdk.FrameNetworking
10
- import com.framepayments.framesdk.chargeintents.ChargeIntent
11
10
  import com.framepayments.framesdk_ui.FrameCheckoutView
12
- import com.google.gson.Gson
13
11
 
14
12
  class FrameCheckoutActivity : AppCompatActivity() {
15
13
 
@@ -25,17 +23,24 @@ class FrameCheckoutActivity : AppCompatActivity() {
25
23
  )
26
24
  }
27
25
  setContentView(container)
28
- val customerId = intent.getStringExtra(EXTRA_CUSTOMER_ID)
26
+ val accountId = intent.getStringExtra(EXTRA_ACCOUNT_ID)
29
27
  val amount = intent.getIntExtra(EXTRA_AMOUNT, 0)
30
28
 
29
+ // Bundled checkout always creates a Transfer, which requires an account.
30
+ if (accountId.isNullOrEmpty()) {
31
+ setResult(RESULT_CANCELED)
32
+ finish()
33
+ return
34
+ }
35
+
31
36
  // Evervault must be configured before FrameCheckoutView (EncryptedPaymentCardInput) can inflate.
32
37
  // configureEvervault() is async on first launch; direct checkout opens before it completes.
33
- tryShowCheckout(container, customerId, amount)
38
+ tryShowCheckout(container, accountId, amount)
34
39
  }
35
40
 
36
- private fun tryShowCheckout(container: FrameLayout, customerId: String?, amount: Int) {
41
+ private fun tryShowCheckout(container: FrameLayout, accountId: String, amount: Int) {
37
42
  if (FrameNetworking.isEvervaultConfigured) {
38
- addCheckoutView(container, customerId, amount)
43
+ addCheckoutView(container, accountId, amount)
39
44
  return
40
45
  }
41
46
  var attempts = 0
@@ -44,7 +49,7 @@ class FrameCheckoutActivity : AppCompatActivity() {
44
49
  override fun run() {
45
50
  if (isFinishing) return
46
51
  if (FrameNetworking.isEvervaultConfigured) {
47
- addCheckoutView(container, customerId, amount)
52
+ addCheckoutView(container, accountId, amount)
48
53
  pollRunnable = null
49
54
  return
50
55
  }
@@ -60,11 +65,10 @@ class FrameCheckoutActivity : AppCompatActivity() {
60
65
  handler.postDelayed(pollRunnable!!, 100)
61
66
  }
62
67
 
63
- private fun addCheckoutView(container: FrameLayout, customerId: String?, amount: Int) {
68
+ private fun addCheckoutView(container: FrameLayout, accountId: String, amount: Int) {
64
69
  val checkoutView = FrameCheckoutView(this)
65
- checkoutView.configure(customerId, amount) { chargeIntent ->
66
- val json = Gson().toJson(chargeIntent)
67
- setResult(RESULT_OK, Intent().putExtra(EXTRA_CHARGE_INTENT_JSON, json))
70
+ checkoutView.configure(accountId, amount) { transferId ->
71
+ setResult(RESULT_OK, Intent().putExtra(EXTRA_TRANSFER_ID, transferId))
68
72
  finish()
69
73
  }
70
74
  container.addView(checkoutView)
@@ -76,9 +80,9 @@ class FrameCheckoutActivity : AppCompatActivity() {
76
80
  }
77
81
 
78
82
  companion object {
79
- const val EXTRA_CUSTOMER_ID = "customer_id"
83
+ const val EXTRA_ACCOUNT_ID = "account_id"
80
84
  const val EXTRA_AMOUNT = "amount"
81
- const val EXTRA_CHARGE_INTENT_JSON = "charge_intent_json"
85
+ const val EXTRA_TRANSFER_ID = "transfer_id"
82
86
  const val REQUEST_CODE = 9001
83
87
  }
84
88
  }