@moonpay/platform-sdk-react-native 1.9.0 → 1.10.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.
package/README.md CHANGED
@@ -63,6 +63,53 @@ export function App() {
63
63
 
64
64
  Pass an optional `theme={{ appearance: 'light' | 'dark' }}` to render every MoonPay frame in light or dark mode. Omit it to follow the customer's system preference. The connect flow can override it per call (`client.connect({ theme })` or `<MoonPayConnect theme={...} />`).
65
65
 
66
+ #### Providing the session token later
67
+
68
+ The `sessionToken` prop is optional. If you don't have it when the provider mounts (for example, you fetch it from your server after the customer signs in), mount `MoonPayProvider` without it and call `initialize()` from `useMoonPay()` once the token is available:
69
+
70
+ ```tsx
71
+ import { MoonPayProvider, useMoonPay } from '@moonpay/platform-sdk-react-native';
72
+
73
+ export function App() {
74
+ return (
75
+ <MoonPayProvider>
76
+ <YourApp />
77
+ </MoonPayProvider>
78
+ );
79
+ }
80
+
81
+ function SignInScreen() {
82
+ const { initialize, isInitialized } = useMoonPay();
83
+
84
+ const onSignedIn = async () => {
85
+ const sessionToken = await fetchSessionTokenFromYourServer();
86
+ initialize(sessionToken); // the SDK is now ready
87
+ };
88
+
89
+ // ...
90
+ }
91
+ ```
92
+
93
+ `isInitialized` is `true` once a token is available (via the prop or `initialize()`). Calling a connection method before then resolves to an `err()` Result. You can also call `initialize()` again later to replace the token (for example, after a refresh). Choose one style — the controlled `sessionToken` prop or `initialize()`; if both are used, the prop wins.
94
+
95
+ Because `initialize()` updates React state, the `client` that carries the new token is available on the **next render** — not synchronously within the same call. Gate your connection flow on `isInitialized` (or read `client` from `useMoonPay()` after the re-render) rather than reusing a `client` captured before `initialize()`:
96
+
97
+ ```tsx
98
+ function BuyScreen() {
99
+ const { client, isInitialized } = useMoonPay();
100
+
101
+ useEffect(() => {
102
+ if (!isInitialized) return;
103
+ // `client` here reflects the initialized session token
104
+ client.getConnection().then((result) => {
105
+ // ...
106
+ });
107
+ }, [isInitialized, client]);
108
+ }
109
+ ```
110
+
111
+ Reusing a `client` reference captured before `initialize()` runs against the pre-initialization client and resolves to an `err()` (no session token).
112
+
66
113
  **3. Check the connection and connect the customer:**
67
114
 
68
115
  ```tsx
package/dist/index.cjs CHANGED
@@ -198,6 +198,14 @@ function applyCredentialsOnComplete(msg, ctx) {
198
198
  ctx.core.context.setAccessToken(creds.accessToken);
199
199
  ctx.core.context.setClientToken(creds.clientToken);
200
200
  }
201
+ function requireSessionToken(ctx) {
202
+ if (!ctx.sessionToken) {
203
+ throw new Error(
204
+ "No session token \u2014 pass sessionToken to <MoonPayProvider> or call initialize() from useMoonPay() before starting a connection."
205
+ );
206
+ }
207
+ return ctx.sessionToken;
208
+ }
201
209
  var connectionCheckSpec = {
202
210
  channelPrefix: "check",
203
211
  path: import_platform_sdk_core.FRAME_PATHS.checkConnection,
@@ -205,7 +213,7 @@ var connectionCheckSpec = {
205
213
  needsKeyPair: true,
206
214
  handshakeTimeout: 1e4,
207
215
  buildParams: (ctx, props, publicKey) => ({
208
- sessionToken: ctx.sessionToken,
216
+ sessionToken: requireSessionToken(ctx),
209
217
  publicKey,
210
218
  ...props.skipKyc && { skipKyc: true }
211
219
  }),
@@ -227,7 +235,7 @@ var connectSpec = {
227
235
  hidden: false,
228
236
  needsKeyPair: true,
229
237
  buildParams: (ctx, props, publicKey) => ({
230
- sessionToken: ctx.sessionToken,
238
+ sessionToken: requireSessionToken(ctx),
231
239
  publicKey,
232
240
  // Per-call override; `applyThemeParam` in the engine fills the client
233
241
  // default for connect (and every other visible frame) when this is absent.
@@ -441,7 +449,7 @@ var connectionResetSpec = {
441
449
  path: import_platform_sdk_core.FRAME_PATHS.reset,
442
450
  hidden: true,
443
451
  handshakeTimeout: 5e3,
444
- buildParams: (ctx) => ({ sessionToken: ctx.sessionToken }),
452
+ buildParams: (ctx) => ({ sessionToken: requireSessionToken(ctx) }),
445
453
  mapMessage: (msg) => {
446
454
  if (msg.kind === "complete") return { kind: "complete" };
447
455
  if (msg.kind === "error") {
@@ -1184,13 +1192,15 @@ var styles = import_react_native2.StyleSheet.create({
1184
1192
  var import_jsx_runtime3 = require("react/jsx-runtime");
1185
1193
  var MoonPayContext = (0, import_react3.createContext)(null);
1186
1194
  function MoonPayProvider({
1187
- sessionToken,
1195
+ sessionToken: sessionTokenProp,
1188
1196
  apiBaseUrl,
1189
1197
  frameBaseUrl,
1190
1198
  theme,
1191
1199
  children
1192
1200
  }) {
1193
1201
  const [frameSlots, setFrameSlots] = (0, import_react3.useState)([]);
1202
+ const [internalToken, setInternalToken] = (0, import_react3.useState)(void 0);
1203
+ const sessionToken = sessionTokenProp ?? internalToken;
1194
1204
  const addSlot = (0, import_react3.useCallback)((slot) => {
1195
1205
  setFrameSlots((prev) => [...prev, slot]);
1196
1206
  }, []);
@@ -1206,6 +1216,14 @@ function MoonPayProvider({
1206
1216
  });
1207
1217
  }
1208
1218
  const core = coreRef.current;
1219
+ const initialize = (0, import_react3.useCallback)(
1220
+ (token) => {
1221
+ core.context.setAccessToken("");
1222
+ core.context.setClientToken("");
1223
+ setInternalToken(token);
1224
+ },
1225
+ [core]
1226
+ );
1209
1227
  const client = (0, import_react3.useMemo)(() => {
1210
1228
  const specCtx = { sessionToken, core, frameBaseUrl, theme };
1211
1229
  return createRNClient({
@@ -1213,21 +1231,28 @@ function MoonPayProvider({
1213
1231
  core
1214
1232
  });
1215
1233
  }, [sessionToken, frameBaseUrl, core, addSlot, removeSlot, theme?.appearance]);
1216
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(MoonPayContext.Provider, { value: { client, sessionToken, core, frameBaseUrl, theme }, children: [
1217
- children,
1218
- frameSlots.filter((slot) => slot.hidden).map((slot) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MoonPayFrame, { transport: slot.transport, hidden: true }, slot.id)),
1219
- frameSlots.filter((slot) => !slot.hidden).map((slot) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1220
- VisibleFrameSlotSheet,
1221
- {
1222
- slot,
1223
- onClose: () => {
1224
- slot.dispose();
1225
- removeSlot(slot.id);
1226
- }
1227
- },
1228
- slot.id
1229
- ))
1230
- ] });
1234
+ const isInitialized = sessionToken !== void 0;
1235
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1236
+ MoonPayContext.Provider,
1237
+ {
1238
+ value: { client, sessionToken, core, frameBaseUrl, theme, initialize, isInitialized },
1239
+ children: [
1240
+ children,
1241
+ frameSlots.filter((slot) => slot.hidden).map((slot) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MoonPayFrame, { transport: slot.transport, hidden: true }, slot.id)),
1242
+ frameSlots.filter((slot) => !slot.hidden).map((slot) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1243
+ VisibleFrameSlotSheet,
1244
+ {
1245
+ slot,
1246
+ onClose: () => {
1247
+ slot.dispose();
1248
+ removeSlot(slot.id);
1249
+ }
1250
+ },
1251
+ slot.id
1252
+ ))
1253
+ ]
1254
+ }
1255
+ );
1231
1256
  }
1232
1257
  function useMoonPayContext() {
1233
1258
  const ctx = (0, import_react3.useContext)(MoonPayContext);
@@ -1237,7 +1262,8 @@ function useMoonPayContext() {
1237
1262
  return ctx;
1238
1263
  }
1239
1264
  function useMoonPay() {
1240
- return useMoonPayContext();
1265
+ const { client, initialize, isInitialized } = useMoonPayContext();
1266
+ return { client, initialize, isInitialized };
1241
1267
  }
1242
1268
 
1243
1269
  // src/frame-view.tsx