@moonpay/platform-sdk-react-native 0.3.0 → 1.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.
package/dist/index.cjs CHANGED
@@ -30,12 +30,391 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
+ ConnectionStatus: () => import_connection2.ConnectionStatus,
34
+ MoonPayAddCard: () => MoonPayAddCard,
35
+ MoonPayApplePayButton: () => MoonPayApplePayButton,
36
+ MoonPayAuth: () => MoonPayAuth,
37
+ MoonPayBuyButton: () => MoonPayBuyButton,
38
+ MoonPayBuyFrame: () => MoonPayBuyFrame,
39
+ MoonPayChallenge: () => MoonPayChallenge,
40
+ MoonPayConnect: () => MoonPayConnect,
41
+ MoonPayConnectionCheck: () => MoonPayConnectionCheck,
42
+ MoonPayConnectionReset: () => MoonPayConnectionReset,
33
43
  MoonPayFrame: () => MoonPayFrame,
44
+ MoonPayGooglePayButton: () => MoonPayGooglePayButton,
34
45
  MoonPayProvider: () => MoonPayProvider,
46
+ MoonPayWidget: () => MoonPayWidget,
35
47
  WebViewTransport: () => WebViewTransport,
36
48
  useMoonPay: () => useMoonPay
37
49
  });
38
50
  module.exports = __toCommonJS(src_exports);
51
+ var import_connection2 = require("@moonpay/platform-protocol/models/connection");
52
+
53
+ // src/frame-specs.ts
54
+ var import_connection = require("@moonpay/platform-protocol/models/connection");
55
+ var import_platform_sdk_core = require("@moonpay/platform-sdk-core");
56
+ function createQuoteCommands(send, channelId) {
57
+ return {
58
+ setQuote: (signature) => send({
59
+ version: 2,
60
+ meta: { channelId },
61
+ kind: "setQuote",
62
+ payload: { quote: { signature } }
63
+ })
64
+ };
65
+ }
66
+ var applePaySpec = {
67
+ channelPrefix: "applepay",
68
+ path: import_platform_sdk_core.FRAME_PATHS.applePay,
69
+ hidden: false,
70
+ buildParams: (ctx, props) => ({
71
+ clientToken: ctx.core.context.clientToken,
72
+ signature: props.quote
73
+ }),
74
+ createCommands: createQuoteCommands,
75
+ reactiveProps: {
76
+ quote: (commands, quote) => commands.setQuote(quote)
77
+ },
78
+ mapMessage: (msg, commands) => {
79
+ switch (msg.kind) {
80
+ case "ready":
81
+ return { kind: "ready" };
82
+ case "complete":
83
+ return { kind: "complete", payload: msg.payload };
84
+ case "challenge":
85
+ return {
86
+ kind: "challenge",
87
+ payload: msg.payload
88
+ };
89
+ case "error": {
90
+ const payload = msg.payload;
91
+ if (payload.code === "quoteExpired") {
92
+ return { kind: "quoteExpired", payload: { setQuote: commands.setQuote } };
93
+ }
94
+ if (payload.code === "applePayUnavailable") {
95
+ return { kind: "unsupported" };
96
+ }
97
+ const kind = payload.code === "generic" ? "genericError" : payload.code;
98
+ return { kind: "error", payload: { kind, message: payload.message } };
99
+ }
100
+ default:
101
+ return null;
102
+ }
103
+ },
104
+ errorEvent: (message) => ({ kind: "error", payload: { kind: "genericError", message } })
105
+ };
106
+ var googlePaySpec = {
107
+ channelPrefix: "googlepay",
108
+ path: import_platform_sdk_core.FRAME_PATHS.googlePay,
109
+ hidden: false,
110
+ buildParams: (ctx, props) => ({
111
+ clientToken: ctx.core.context.clientToken,
112
+ signature: props.quote,
113
+ ...props.externalTransactionId && { externalTransactionId: props.externalTransactionId }
114
+ }),
115
+ createCommands: createQuoteCommands,
116
+ reactiveProps: {
117
+ quote: (commands, quote) => commands.setQuote(quote)
118
+ },
119
+ mapMessage: (msg, commands) => {
120
+ switch (msg.kind) {
121
+ case "ready":
122
+ return { kind: "ready" };
123
+ case "complete":
124
+ return { kind: "complete", payload: msg.payload };
125
+ case "challenge":
126
+ return {
127
+ kind: "challenge",
128
+ payload: msg.payload
129
+ };
130
+ case "error": {
131
+ const payload = msg.payload;
132
+ if (payload.code === "quoteExpired") {
133
+ return { kind: "quoteExpired", payload: { setQuote: commands.setQuote } };
134
+ }
135
+ if (payload.code === "googlePayUnavailable") {
136
+ return { kind: "unsupported" };
137
+ }
138
+ const kind = payload.code === "generic" ? "genericError" : payload.code;
139
+ return { kind: "error", payload: { kind, message: payload.message } };
140
+ }
141
+ default:
142
+ return null;
143
+ }
144
+ },
145
+ errorEvent: (message) => ({ kind: "error", payload: { kind: "genericError", message } })
146
+ };
147
+ var buyButtonSpec = {
148
+ channelPrefix: "buy-button",
149
+ path: import_platform_sdk_core.FRAME_PATHS.buyButton,
150
+ hidden: false,
151
+ buildParams: (ctx, props) => ({
152
+ clientToken: ctx.core.context.clientToken,
153
+ signature: props.quote
154
+ }),
155
+ createCommands: createQuoteCommands,
156
+ reactiveProps: {
157
+ quote: (commands, quote) => commands.setQuote(quote)
158
+ },
159
+ mapMessage: (msg) => {
160
+ switch (msg.kind) {
161
+ case "complete":
162
+ return { kind: "complete", payload: msg.payload };
163
+ case "challenge":
164
+ return {
165
+ kind: "challenge",
166
+ payload: msg.payload
167
+ };
168
+ case "error":
169
+ return { kind: "error", payload: msg.payload };
170
+ default:
171
+ return null;
172
+ }
173
+ },
174
+ errorEvent: (message) => ({
175
+ kind: "error",
176
+ payload: { code: "generic", message }
177
+ })
178
+ };
179
+ function applyCredentialsOnComplete(msg, ctx) {
180
+ if (msg.kind !== "complete" || !ctx.privateKey)
181
+ return;
182
+ const connection = msg.payload;
183
+ if (connection.status !== import_connection.ConnectionStatus.active)
184
+ return;
185
+ const creds = (0, import_platform_sdk_core.decryptCredentials)(connection.credentials, ctx.privateKey);
186
+ ctx.core.context.setAccessToken(creds.accessToken);
187
+ ctx.core.context.setClientToken(creds.clientToken);
188
+ }
189
+ var connectionCheckSpec = {
190
+ channelPrefix: "check",
191
+ path: import_platform_sdk_core.FRAME_PATHS.checkConnection,
192
+ hidden: true,
193
+ needsKeyPair: true,
194
+ handshakeTimeout: 1e4,
195
+ buildParams: (ctx, props, publicKey) => ({
196
+ sessionToken: ctx.sessionToken,
197
+ publicKey,
198
+ ...props.skipKyc && { skipKyc: true }
199
+ }),
200
+ onMessageEffect: applyCredentialsOnComplete,
201
+ mapMessage: (msg) => {
202
+ if (msg.kind === "complete") {
203
+ return { kind: "complete", payload: msg.payload };
204
+ }
205
+ if (msg.kind === "error") {
206
+ return { kind: "error", payload: msg.payload };
207
+ }
208
+ return null;
209
+ },
210
+ errorEvent: (message) => ({ kind: "error", payload: { message } })
211
+ };
212
+ var connectSpec = {
213
+ channelPrefix: "connect",
214
+ path: import_platform_sdk_core.FRAME_PATHS.connect,
215
+ hidden: false,
216
+ needsKeyPair: true,
217
+ buildParams: (ctx, props, publicKey) => ({
218
+ sessionToken: ctx.sessionToken,
219
+ publicKey,
220
+ ...props.theme?.appearance && { appearance: props.theme.appearance }
221
+ }),
222
+ onMessageEffect: applyCredentialsOnComplete,
223
+ mapMessage: (msg) => {
224
+ switch (msg.kind) {
225
+ case "ready":
226
+ return { kind: "ready" };
227
+ case "error":
228
+ return { kind: "error", payload: msg.payload };
229
+ case "complete":
230
+ return { kind: "complete", payload: msg.payload };
231
+ default:
232
+ return null;
233
+ }
234
+ },
235
+ errorEvent: (message) => ({
236
+ kind: "error",
237
+ payload: { code: import_connection.ConnectionErrorCode.connectionFailedGeneric, message }
238
+ })
239
+ };
240
+ var authSpec = {
241
+ channelPrefix: "auth",
242
+ path: import_platform_sdk_core.FRAME_PATHS.auth,
243
+ hidden: false,
244
+ needsKeyPair: true,
245
+ buildParams: (ctx, _props, publicKey) => {
246
+ const clientToken = ctx.core.context.clientToken;
247
+ if (!clientToken) {
248
+ throw new Error(
249
+ 'No clientToken in context \u2014 call getConnection() first and ensure it resolved with status "connectionRequired".'
250
+ );
251
+ }
252
+ return { clientToken, publicKey };
253
+ },
254
+ onMessageEffect: applyCredentialsOnComplete,
255
+ mapMessage: (msg) => {
256
+ switch (msg.kind) {
257
+ case "ready":
258
+ return { kind: "ready" };
259
+ case "error":
260
+ return { kind: "error", payload: msg.payload };
261
+ case "complete": {
262
+ const connection = msg.payload;
263
+ if (connection.status === import_connection.ConnectionStatus.active || connection.status === import_connection.ConnectionStatus.termsAcceptanceRequired) {
264
+ return { kind: "complete", payload: msg.payload };
265
+ }
266
+ return null;
267
+ }
268
+ default:
269
+ return null;
270
+ }
271
+ },
272
+ errorEvent: (message) => ({
273
+ kind: "error",
274
+ payload: { code: import_connection.ConnectionErrorCode.connectionFailedGeneric, message }
275
+ })
276
+ };
277
+ var widgetSpec = {
278
+ channelPrefix: "widget",
279
+ path: import_platform_sdk_core.FRAME_PATHS.widget,
280
+ hidden: false,
281
+ buildParams: (ctx, props) => ({
282
+ flow: "buy",
283
+ clientToken: ctx.core.context.clientToken,
284
+ quoteSignature: props.quote
285
+ }),
286
+ mapMessage: (msg) => {
287
+ switch (msg.kind) {
288
+ case "ready":
289
+ return { kind: "ready" };
290
+ case "transactionCreated":
291
+ return {
292
+ kind: "transactionCreated",
293
+ payload: msg.payload
294
+ };
295
+ case "complete":
296
+ return { kind: "complete", payload: msg.payload };
297
+ case "error":
298
+ return { kind: "error", payload: msg.payload };
299
+ case "close":
300
+ return { kind: "close" };
301
+ default:
302
+ return null;
303
+ }
304
+ },
305
+ errorEvent: (message) => ({
306
+ kind: "error",
307
+ payload: { code: "generic", message }
308
+ })
309
+ };
310
+ var buySpec = {
311
+ channelPrefix: "buy",
312
+ path: import_platform_sdk_core.FRAME_PATHS.buy,
313
+ hidden: true,
314
+ buildParams: (ctx, props) => ({
315
+ clientToken: ctx.core.context.clientToken,
316
+ signature: props.quote,
317
+ ...props.externalTransactionId && { externalTransactionId: props.externalTransactionId }
318
+ }),
319
+ createCommands: createQuoteCommands,
320
+ reactiveProps: {
321
+ quote: (commands, quote) => commands.setQuote(quote)
322
+ },
323
+ mapMessage: (msg) => {
324
+ switch (msg.kind) {
325
+ case "ready":
326
+ return { kind: "ready" };
327
+ case "complete":
328
+ return { kind: "complete", payload: msg.payload };
329
+ case "challenge":
330
+ return { kind: "challenge", payload: msg.payload };
331
+ case "error":
332
+ return { kind: "error", payload: msg.payload };
333
+ default:
334
+ return null;
335
+ }
336
+ },
337
+ errorEvent: (message) => ({
338
+ kind: "error",
339
+ payload: { code: "generic", message }
340
+ })
341
+ };
342
+ var addCardSpec = {
343
+ channelPrefix: "add-card",
344
+ path: import_platform_sdk_core.FRAME_PATHS.addCard,
345
+ hidden: false,
346
+ buildParams: (ctx) => ({ clientToken: ctx.core.context.clientToken }),
347
+ mapMessage: (msg) => {
348
+ switch (msg.kind) {
349
+ case "ready":
350
+ return { kind: "ready" };
351
+ case "complete":
352
+ return {
353
+ kind: "complete",
354
+ payload: msg.payload
355
+ };
356
+ case "error":
357
+ return { kind: "error", payload: msg.payload };
358
+ default:
359
+ return null;
360
+ }
361
+ },
362
+ errorEvent: (message) => ({
363
+ kind: "error",
364
+ payload: { code: "generic", message }
365
+ })
366
+ };
367
+ var challengeSpec = {
368
+ channelPrefix: "challenge",
369
+ path: import_platform_sdk_core.FRAME_PATHS.challenge,
370
+ // documentation only — buildUrl below wins
371
+ hidden: false,
372
+ resolveChannelId: (props, generated) => new URL(props.url).searchParams.get("channelId") || generated,
373
+ buildUrl: (_ctx, props, channelId) => {
374
+ const url = new URL(props.url);
375
+ url.searchParams.set("channelId", channelId);
376
+ return url.toString();
377
+ },
378
+ mapMessage: (msg) => {
379
+ switch (msg.kind) {
380
+ case "ready":
381
+ return { kind: "ready" };
382
+ case "complete":
383
+ return { kind: "complete", payload: msg.payload };
384
+ case "cancelled":
385
+ return { kind: "cancelled", payload: msg.payload };
386
+ case "error":
387
+ return { kind: "error", payload: msg.payload };
388
+ default:
389
+ return null;
390
+ }
391
+ },
392
+ errorEvent: (message) => ({
393
+ kind: "error",
394
+ payload: { code: "generic", message }
395
+ })
396
+ };
397
+ var connectionResetSpec = {
398
+ channelPrefix: "reset",
399
+ path: import_platform_sdk_core.FRAME_PATHS.reset,
400
+ hidden: true,
401
+ handshakeTimeout: 5e3,
402
+ buildParams: (ctx) => ({ sessionToken: ctx.sessionToken }),
403
+ mapMessage: (msg) => {
404
+ if (msg.kind === "complete")
405
+ return { kind: "complete" };
406
+ if (msg.kind === "error") {
407
+ const payload = msg.payload;
408
+ return { kind: "error", payload: { message: payload?.message ?? "Reset failed" } };
409
+ }
410
+ return null;
411
+ },
412
+ errorEvent: (message) => ({ kind: "error", payload: { message } })
413
+ };
414
+
415
+ // src/frame-view.tsx
416
+ var import_react3 = require("react");
417
+ var import_react_native3 = require("react-native");
39
418
 
40
419
  // src/frame-component.tsx
41
420
  var import_react = require("react");
@@ -70,10 +449,8 @@ function MoonPayFrame({ transport, hidden, style }) {
70
449
  ) });
71
450
  }
72
451
 
73
- // src/provider.tsx
74
- var import_platform_protocol = require("@moonpay/platform-protocol");
75
- var import_platform_sdk_core = require("@moonpay/platform-sdk-core");
76
- var import_react2 = require("react");
452
+ // src/frame-engine.ts
453
+ var import_platform_sdk_core2 = require("@moonpay/platform-sdk-core");
77
454
 
78
455
  // src/webview-transport.ts
79
456
  var WebViewTransport = class {
@@ -134,10 +511,401 @@ var WebViewTransport = class {
134
511
  }
135
512
  };
136
513
 
514
+ // src/frame-engine.ts
515
+ var FrameSessionDisposedError = class extends Error {
516
+ constructor() {
517
+ super("Frame session disposed");
518
+ this.name = "FrameSessionDisposedError";
519
+ }
520
+ };
521
+ function createFrameSession(spec, ctx, props, overrides = {}) {
522
+ const generated = `${spec.channelPrefix}-${Date.now()}`;
523
+ const channelId = spec.resolveChannelId ? spec.resolveChannelId(props, generated) : generated;
524
+ const keyPair = spec.needsKeyPair ? (0, import_platform_sdk_core2.generateKeyPair)() : void 0;
525
+ const url = spec.buildUrl ? spec.buildUrl(ctx, props, channelId, keyPair?.publicKey) : (0, import_platform_sdk_core2.buildFrameUrl)(
526
+ spec.path,
527
+ { ...spec.buildParams?.(ctx, props, keyPair?.publicKey), channelId },
528
+ { frameBaseUrl: ctx.frameBaseUrl }
529
+ );
530
+ const transport = (overrides.createTransport ?? (() => new WebViewTransport()))();
531
+ let resolvedHandle = null;
532
+ let rejectDisposed;
533
+ const disposedBeforeReady = new Promise((_, reject) => {
534
+ rejectDisposed = reject;
535
+ });
536
+ const handleReady = (0, import_platform_sdk_core2.createFrameOrchestrator)({
537
+ transport,
538
+ channelId,
539
+ url,
540
+ container: null,
541
+ hidden: spec.hidden,
542
+ handshakeTimeout: overrides.handshakeTimeout ?? spec.handshakeTimeout ?? 15e3
543
+ }).then((handle) => {
544
+ const send = (msg) => handle.sendMessage(msg);
545
+ const commands = spec.createCommands?.(send, channelId);
546
+ const eventHandlers = [];
547
+ const disposeHandlers = [];
548
+ let disposeNotified = false;
549
+ const notifyDisposed = () => {
550
+ if (disposeNotified)
551
+ return;
552
+ disposeNotified = true;
553
+ for (const handler of [...disposeHandlers]) {
554
+ handler();
555
+ }
556
+ };
557
+ handle.onMessage((msg) => {
558
+ spec.onMessageEffect?.(msg, { ...ctx, privateKey: keyPair?.privateKey });
559
+ const event = spec.mapMessage(msg, commands);
560
+ if (event !== null) {
561
+ for (const handler of [...eventHandlers]) {
562
+ handler(event);
563
+ }
564
+ }
565
+ });
566
+ const sessionHandle = {
567
+ onEvent(handler) {
568
+ eventHandlers.push(handler);
569
+ return () => {
570
+ const idx = eventHandlers.indexOf(handler);
571
+ if (idx >= 0)
572
+ eventHandlers.splice(idx, 1);
573
+ };
574
+ },
575
+ onMessage: (handler) => handle.onMessage(handler),
576
+ onDispose(handler) {
577
+ disposeHandlers.push(handler);
578
+ return () => {
579
+ const idx = disposeHandlers.indexOf(handler);
580
+ if (idx >= 0)
581
+ disposeHandlers.splice(idx, 1);
582
+ };
583
+ },
584
+ sendMessage: send,
585
+ commands,
586
+ dispose: () => {
587
+ handle.dispose();
588
+ notifyDisposed();
589
+ }
590
+ };
591
+ resolvedHandle = sessionHandle;
592
+ return sessionHandle;
593
+ });
594
+ const ready = Promise.race([handleReady, disposedBeforeReady]);
595
+ ready.catch(() => {
596
+ });
597
+ return {
598
+ transport,
599
+ channelId,
600
+ url,
601
+ hidden: spec.hidden,
602
+ ready,
603
+ dispose: () => {
604
+ if (resolvedHandle) {
605
+ resolvedHandle.dispose();
606
+ } else {
607
+ transport.dispose();
608
+ rejectDisposed?.(new FrameSessionDisposedError());
609
+ }
610
+ }
611
+ };
612
+ }
613
+
614
+ // src/provider.tsx
615
+ var import_platform_sdk_core3 = require("@moonpay/platform-sdk-core");
616
+ var import_react2 = require("react");
617
+ var import_react_native2 = require("react-native");
618
+
619
+ // src/methods/add-card.ts
620
+ var import_result = require("@moonpay/platform-protocol/result");
621
+ async function setupAddCard(deps, opts) {
622
+ try {
623
+ const { handle, dispose } = await deps.mountSession(addCardSpec, {});
624
+ handle.onEvent((event) => opts.onEvent?.(event));
625
+ return (0, import_result.ok)({ dispose });
626
+ } catch (e) {
627
+ return (0, import_result.err)({
628
+ kind: "genericError",
629
+ message: e instanceof Error ? e.message : "Add card setup failed"
630
+ });
631
+ }
632
+ }
633
+
634
+ // src/methods/apple-pay.ts
635
+ var import_result2 = require("@moonpay/platform-protocol/result");
636
+ async function setupApplePay(deps, opts) {
637
+ try {
638
+ const { handle, dispose } = await deps.mountSession(applePaySpec, { quote: opts.quote });
639
+ handle.onEvent((event) => opts.onEvent?.(event));
640
+ return (0, import_result2.ok)({ setQuote: handle.commands.setQuote, dispose });
641
+ } catch (e) {
642
+ return (0, import_result2.err)({
643
+ kind: "genericError",
644
+ message: e instanceof Error ? e.message : "Apple Pay setup failed"
645
+ });
646
+ }
647
+ }
648
+
649
+ // src/methods/auth.ts
650
+ var import_result3 = require("@moonpay/platform-protocol/result");
651
+ async function setupAuth(deps, opts) {
652
+ if (!deps.core.context.clientToken) {
653
+ return (0, import_result3.err)({
654
+ kind: "configurationError",
655
+ message: 'No clientToken in context \u2014 call getConnection() first and ensure it resolved with status "connectionRequired".'
656
+ });
657
+ }
658
+ try {
659
+ const { handle, dispose } = await deps.mountSession(authSpec, {});
660
+ return await new Promise((resolve) => {
661
+ handle.onEvent((event) => {
662
+ opts.onEvent?.(event);
663
+ if (event.kind === "error") {
664
+ resolve((0, import_result3.err)({ kind: "genericError", message: "Auth frame error" }));
665
+ dispose();
666
+ }
667
+ });
668
+ handle.onMessage((msg) => {
669
+ if (msg.kind === "complete") {
670
+ resolve((0, import_result3.ok)({ dispose }));
671
+ }
672
+ });
673
+ handle.onDispose(() => {
674
+ resolve((0, import_result3.err)({ kind: "genericError", message: "Auth flow dismissed" }));
675
+ });
676
+ });
677
+ } catch (e) {
678
+ if (e instanceof FrameSessionDisposedError) {
679
+ return (0, import_result3.err)({ kind: "genericError", message: "Auth flow dismissed" });
680
+ }
681
+ return (0, import_result3.err)({
682
+ kind: "genericError",
683
+ message: e instanceof Error ? e.message : "Auth setup failed"
684
+ });
685
+ }
686
+ }
687
+
688
+ // src/methods/buy.ts
689
+ var import_result4 = require("@moonpay/platform-protocol/result");
690
+ async function setupBuy(deps, opts) {
691
+ try {
692
+ const { handle, dispose } = await deps.mountSession(buySpec, {
693
+ quote: opts.quote,
694
+ externalTransactionId: opts.externalTransactionId
695
+ });
696
+ handle.onEvent((event) => opts.onEvent?.(event));
697
+ return (0, import_result4.ok)({ setQuote: handle.commands.setQuote, dispose });
698
+ } catch (e) {
699
+ return (0, import_result4.err)({
700
+ kind: "genericError",
701
+ message: e instanceof Error ? e.message : "Buy setup failed"
702
+ });
703
+ }
704
+ }
705
+
706
+ // src/methods/buy-button.ts
707
+ var import_result5 = require("@moonpay/platform-protocol/result");
708
+ async function setupBuyButton(deps, opts) {
709
+ try {
710
+ const { handle, dispose } = await deps.mountSession(buyButtonSpec, { quote: opts.quote });
711
+ handle.onEvent((event) => opts.onEvent?.(event));
712
+ return (0, import_result5.ok)({ setQuote: handle.commands.setQuote, dispose });
713
+ } catch (e) {
714
+ return (0, import_result5.err)({
715
+ kind: "genericError",
716
+ message: e instanceof Error ? e.message : "Buy button setup failed"
717
+ });
718
+ }
719
+ }
720
+
721
+ // src/methods/challenge.ts
722
+ var import_result6 = require("@moonpay/platform-protocol/result");
723
+ async function setupChallenge(deps, opts) {
724
+ try {
725
+ const { handle, dispose } = await deps.mountSession(challengeSpec, { url: opts.url });
726
+ handle.onEvent((event) => opts.onEvent?.(event));
727
+ return (0, import_result6.ok)({ dispose });
728
+ } catch (e) {
729
+ if (e instanceof TypeError) {
730
+ return (0, import_result6.err)({ kind: "configurationError", message: "Invalid challenge URL" });
731
+ }
732
+ return (0, import_result6.err)({
733
+ kind: "genericError",
734
+ message: e instanceof Error ? e.message : "Challenge setup failed"
735
+ });
736
+ }
737
+ }
738
+
739
+ // src/methods/connect.ts
740
+ var import_result7 = require("@moonpay/platform-protocol/result");
741
+ async function connect(deps, opts) {
742
+ try {
743
+ const { handle, dispose } = await deps.mountSession(connectSpec, { theme: opts.theme });
744
+ return await new Promise((resolve) => {
745
+ handle.onEvent((event) => {
746
+ opts.onEvent?.(event);
747
+ if (event.kind === "error") {
748
+ resolve((0, import_result7.err)({ message: "Connection error" }));
749
+ dispose();
750
+ } else if (event.kind === "complete") {
751
+ resolve((0, import_result7.ok)({ dispose }));
752
+ }
753
+ });
754
+ handle.onDispose(() => {
755
+ resolve((0, import_result7.err)({ message: "Connect flow dismissed" }));
756
+ });
757
+ });
758
+ } catch (e) {
759
+ if (e instanceof FrameSessionDisposedError) {
760
+ return (0, import_result7.err)({ message: "Connect flow dismissed" });
761
+ }
762
+ return (0, import_result7.err)({
763
+ message: e instanceof Error ? e.message : "Connect failed"
764
+ });
765
+ }
766
+ }
767
+
768
+ // src/methods/connection-check.ts
769
+ var import_result8 = require("@moonpay/platform-protocol/result");
770
+ async function getConnection(deps, options = {}) {
771
+ try {
772
+ const { handle, dispose } = await deps.mountSession(connectionCheckSpec, options);
773
+ return await new Promise((resolve) => {
774
+ const timeout = setTimeout(() => {
775
+ dispose();
776
+ resolve((0, import_result8.err)({ message: "Get connection timed out" }));
777
+ }, 1e4);
778
+ handle.onEvent((event) => {
779
+ clearTimeout(timeout);
780
+ dispose();
781
+ if (event.kind === "error") {
782
+ resolve((0, import_result8.err)({ message: event.payload.message }));
783
+ } else {
784
+ resolve((0, import_result8.ok)(event.payload));
785
+ }
786
+ });
787
+ });
788
+ } catch (e) {
789
+ return (0, import_result8.err)({
790
+ message: e instanceof Error ? e.message : "Failed to check connection"
791
+ });
792
+ }
793
+ }
794
+
795
+ // src/methods/connection-reset.ts
796
+ var import_result9 = require("@moonpay/platform-protocol/result");
797
+ async function resetConnection(deps) {
798
+ try {
799
+ const { handle, dispose } = await deps.mountSession(connectionResetSpec, {});
800
+ return await new Promise((resolve) => {
801
+ const timeout = setTimeout(() => {
802
+ dispose();
803
+ resolve((0, import_result9.ok)(void 0));
804
+ }, 5e3);
805
+ handle.onEvent(() => {
806
+ clearTimeout(timeout);
807
+ dispose();
808
+ resolve((0, import_result9.ok)(void 0));
809
+ });
810
+ });
811
+ } catch {
812
+ return (0, import_result9.ok)(void 0);
813
+ }
814
+ }
815
+
816
+ // src/methods/google-pay.ts
817
+ var import_result10 = require("@moonpay/platform-protocol/result");
818
+ async function setupGooglePay(deps, opts) {
819
+ try {
820
+ const { handle, dispose } = await deps.mountSession(googlePaySpec, {
821
+ quote: opts.quote,
822
+ externalTransactionId: opts.externalTransactionId
823
+ });
824
+ handle.onEvent((event) => opts.onEvent?.(event));
825
+ return (0, import_result10.ok)({ setQuote: handle.commands.setQuote, dispose });
826
+ } catch (e) {
827
+ return (0, import_result10.err)({
828
+ kind: "genericError",
829
+ message: e instanceof Error ? e.message : "Google Pay setup failed"
830
+ });
831
+ }
832
+ }
833
+
834
+ // src/methods/widget.ts
835
+ var import_result11 = require("@moonpay/platform-protocol/result");
836
+ async function setupWidget(deps, opts) {
837
+ try {
838
+ const { handle, dispose } = await deps.mountSession(widgetSpec, { quote: opts.quote });
839
+ handle.onEvent((event) => opts.onEvent?.(event));
840
+ return (0, import_result11.ok)({ dispose });
841
+ } catch (e) {
842
+ return (0, import_result11.err)({
843
+ kind: "genericError",
844
+ message: e instanceof Error ? e.message : "Widget setup failed"
845
+ });
846
+ }
847
+ }
848
+
849
+ // src/client.ts
850
+ function createRNClient(deps) {
851
+ const { core } = deps;
852
+ return {
853
+ getConnection: (options) => getConnection(deps, options ?? {}),
854
+ connect: (opts) => connect(deps, opts),
855
+ setupAuth: (opts) => setupAuth(deps, opts),
856
+ getPaymentMethods: () => core.getPaymentMethods(),
857
+ getQuote: (params) => core.getQuote(params),
858
+ listTransactions: (params) => core.listTransactions(params),
859
+ getTransaction: (id) => core.getTransaction(id),
860
+ setupWidget: (opts) => setupWidget(deps, opts),
861
+ setupApplePay: (opts) => setupApplePay(deps, opts),
862
+ setupBuy: (opts) => setupBuy(deps, opts),
863
+ setupBuyButton: (opts) => setupBuyButton(deps, opts),
864
+ setupGooglePay: (opts) => setupGooglePay(deps, opts),
865
+ deletePaymentMethod: (id) => core.deletePaymentMethod(id),
866
+ resetConnection: () => resetConnection(deps),
867
+ setupChallenge: (opts) => setupChallenge(deps, opts),
868
+ setupAddCard: (opts) => setupAddCard(deps, opts),
869
+ createIdentity: (body) => core.createIdentity(body),
870
+ getIdentity: (id) => core.getIdentity(id),
871
+ updateIdentity: (id, body) => core.updateIdentity(id, body),
872
+ verifyIdentity: (id) => core.verifyIdentity(id),
873
+ getIdentityUploadUrl: (id, body) => core.getIdentityUploadUrl(id, body),
874
+ submitIdentityFiles: (id, body) => core.submitIdentityFiles(id, body)
875
+ };
876
+ }
877
+
878
+ // src/methods/mount-session.ts
879
+ var slotCounter = 0;
880
+ function createMountSession(specCtx, host) {
881
+ return async function mountSession(spec, props) {
882
+ const session = createFrameSession(spec, specCtx, props);
883
+ const slotId = `slot-${++slotCounter}`;
884
+ host.addSlot({
885
+ id: slotId,
886
+ transport: session.transport,
887
+ hidden: session.hidden,
888
+ dispose: () => session.dispose()
889
+ });
890
+ try {
891
+ const handle = await session.ready;
892
+ return {
893
+ handle,
894
+ dispose: () => {
895
+ handle.dispose();
896
+ host.removeSlot(slotId);
897
+ }
898
+ };
899
+ } catch (e) {
900
+ host.removeSlot(slotId);
901
+ throw e;
902
+ }
903
+ };
904
+ }
905
+
137
906
  // src/provider.tsx
138
907
  var import_jsx_runtime2 = require("react/jsx-runtime");
139
908
  var MoonPayContext = (0, import_react2.createContext)(null);
140
- var slotCounter = 0;
141
909
  function MoonPayProvider({
142
910
  sessionToken,
143
911
  apiBaseUrl,
@@ -153,7 +921,7 @@ function MoonPayProvider({
153
921
  }, []);
154
922
  const coreRef = (0, import_react2.useRef)(null);
155
923
  if (!coreRef.current) {
156
- coreRef.current = (0, import_platform_sdk_core.createClientCore)({
924
+ coreRef.current = (0, import_platform_sdk_core3.createClientCore)({
157
925
  apiBaseUrl,
158
926
  frameBaseUrl,
159
927
  createTransport: () => new WebViewTransport()
@@ -161,674 +929,313 @@ function MoonPayProvider({
161
929
  }
162
930
  const core = coreRef.current;
163
931
  const client = (0, import_react2.useMemo)(() => {
164
- function createManagedFrame(opts) {
165
- const transport = new WebViewTransport();
166
- const slotId = `slot-${++slotCounter}`;
167
- const promise = new Promise((resolve, reject) => {
168
- transport.create(opts.url, { container: null, hidden: opts.hidden });
169
- addSlot({ id: slotId, transport, hidden: opts.hidden });
170
- (0, import_platform_sdk_core.createFrameOrchestrator)({
171
- transport,
172
- channelId: opts.channelId,
173
- url: opts.url,
174
- container: null,
175
- hidden: opts.hidden,
176
- handshakeTimeout: opts.handshakeTimeout ?? 15e3
177
- }).then((handle) => resolve({ handle, slotId })).catch((e) => {
178
- removeSlot(slotId);
179
- reject(e);
180
- });
181
- });
182
- return { promise, transport };
183
- }
184
- async function getConnection(options = {}) {
185
- const { privateKey, publicKey } = (0, import_platform_sdk_core.generateKeyPair)();
186
- const channelId = `check-${Date.now()}`;
187
- const url = (0, import_platform_sdk_core.buildFrameUrl)(
188
- import_platform_sdk_core.FRAME_PATHS.checkConnection,
189
- {
190
- sessionToken,
191
- channelId,
192
- publicKey,
193
- ...options.skipKyc && { skipKyc: true }
932
+ const specCtx = { sessionToken, core, frameBaseUrl };
933
+ return createRNClient({
934
+ mountSession: createMountSession(specCtx, { addSlot, removeSlot }),
935
+ core
936
+ });
937
+ }, [sessionToken, frameBaseUrl, core, addSlot, removeSlot]);
938
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(MoonPayContext.Provider, { value: { client, sessionToken, core, frameBaseUrl }, children: [
939
+ children,
940
+ frameSlots.filter((slot) => slot.hidden).map((slot) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(MoonPayFrame, { transport: slot.transport, hidden: true }, slot.id)),
941
+ frameSlots.filter((slot) => !slot.hidden).map((slot) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
942
+ import_react_native2.Modal,
943
+ {
944
+ visible: true,
945
+ animationType: "slide",
946
+ onRequestClose: () => {
947
+ slot.dispose();
948
+ removeSlot(slot.id);
194
949
  },
195
- { frameBaseUrl }
196
- );
197
- try {
198
- const { promise } = createManagedFrame({
199
- url,
200
- channelId,
201
- hidden: true,
202
- handshakeTimeout: 1e4
203
- });
204
- const { handle, slotId } = await promise;
205
- return new Promise((resolve) => {
206
- const timeout = setTimeout(() => {
207
- handle.dispose();
208
- removeSlot(slotId);
209
- resolve((0, import_platform_protocol.err)({ message: "Get connection timed out" }));
210
- }, 1e4);
211
- handle.onMessage((msg) => {
212
- if (msg.kind === "error") {
213
- clearTimeout(timeout);
214
- handle.dispose();
215
- removeSlot(slotId);
216
- const payload = msg.payload;
217
- resolve((0, import_platform_protocol.err)({ message: payload.message }));
218
- return;
219
- }
220
- if (msg.kind === "complete") {
221
- clearTimeout(timeout);
222
- handle.dispose();
223
- removeSlot(slotId);
224
- const connection = msg.payload;
225
- if (connection.status === import_platform_protocol.ConnectionStatus.active) {
226
- const creds = (0, import_platform_sdk_core.decryptCredentials)(connection.credentials, privateKey);
227
- core.context.setAccessToken(creds.accessToken);
228
- core.context.setClientToken(creds.clientToken);
229
- }
230
- resolve((0, import_platform_protocol.ok)(connection));
231
- }
232
- });
233
- });
234
- } catch (e) {
235
- return (0, import_platform_protocol.err)({
236
- message: e instanceof Error ? e.message : "Failed to check connection"
237
- });
238
- }
950
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(MoonPayFrame, { transport: slot.transport })
951
+ },
952
+ slot.id
953
+ ))
954
+ ] });
955
+ }
956
+ function useMoonPayContext() {
957
+ const ctx = (0, import_react2.useContext)(MoonPayContext);
958
+ if (!ctx) {
959
+ throw new Error("useMoonPay must be used within a <MoonPayProvider>");
960
+ }
961
+ return ctx;
962
+ }
963
+ function useMoonPay() {
964
+ return useMoonPayContext();
965
+ }
966
+
967
+ // src/frame-view.tsx
968
+ var import_jsx_runtime3 = require("react/jsx-runtime");
969
+ function applyReactiveProps(spec, keys, props, applied, handle) {
970
+ for (const key of keys) {
971
+ const next = props[key];
972
+ if (next !== void 0 && next !== applied[key]) {
973
+ spec.reactiveProps?.[key]?.(handle.commands, next);
974
+ applied[key] = next;
239
975
  }
240
- async function connect(opts) {
241
- const { privateKey, publicKey } = (0, import_platform_sdk_core.generateKeyPair)();
242
- const channelId = `connect-${Date.now()}`;
243
- const url = (0, import_platform_sdk_core.buildFrameUrl)(
244
- import_platform_sdk_core.FRAME_PATHS.connect,
245
- {
246
- sessionToken,
247
- channelId,
248
- publicKey,
249
- ...opts.theme?.appearance && { appearance: opts.theme.appearance }
250
- },
251
- { frameBaseUrl }
976
+ }
977
+ }
978
+ function MoonPayFrameView({
979
+ spec,
980
+ props,
981
+ style,
982
+ defaultStyle,
983
+ onEvent
984
+ }) {
985
+ const { sessionToken, core, frameBaseUrl } = useMoonPayContext();
986
+ const [transport, setTransport] = (0, import_react3.useState)(null);
987
+ const handleRef = (0, import_react3.useRef)(null);
988
+ const onEventRef = (0, import_react3.useRef)(onEvent);
989
+ onEventRef.current = onEvent;
990
+ const propsRef = (0, import_react3.useRef)(props);
991
+ propsRef.current = props;
992
+ const reactiveKeys = Object.keys(spec.reactiveProps ?? {});
993
+ const mountProps = {};
994
+ const liveProps = {};
995
+ for (const [key, value] of Object.entries(props)) {
996
+ const k = key;
997
+ (reactiveKeys.includes(k) ? liveProps : mountProps)[k] = value;
998
+ }
999
+ const mountKey = JSON.stringify(mountProps);
1000
+ const liveKey = JSON.stringify(liveProps);
1001
+ const appliedRef = (0, import_react3.useRef)({});
1002
+ (0, import_react3.useEffect)(() => {
1003
+ let disposed = false;
1004
+ let session;
1005
+ const applied = {};
1006
+ for (const key of reactiveKeys) {
1007
+ applied[key] = propsRef.current[key];
1008
+ }
1009
+ appliedRef.current = applied;
1010
+ try {
1011
+ session = createFrameSession(spec, { sessionToken, core, frameBaseUrl }, propsRef.current);
1012
+ } catch (e) {
1013
+ onEventRef.current?.(
1014
+ spec.errorEvent(e instanceof Error ? e.message : "Failed to create frame")
252
1015
  );
253
- try {
254
- const { promise } = createManagedFrame({ url, channelId, hidden: false });
255
- const { handle, slotId } = await promise;
256
- return new Promise((resolve) => {
257
- handle.onMessage((msg) => {
258
- if (msg.kind === "ready") {
259
- opts.onEvent?.({ kind: "ready" });
260
- return;
261
- }
262
- if (msg.kind === "error") {
263
- const payload = msg.payload;
264
- opts.onEvent?.({ kind: "error", payload });
265
- handle.dispose();
266
- removeSlot(slotId);
267
- resolve((0, import_platform_protocol.err)({ message: "Connection error" }));
268
- return;
269
- }
270
- if (msg.kind === "complete") {
271
- const connection = msg.payload;
272
- if (connection.status === import_platform_protocol.ConnectionStatus.active) {
273
- const creds = (0, import_platform_sdk_core.decryptCredentials)(connection.credentials, privateKey);
274
- core.context.setAccessToken(creds.accessToken);
275
- core.context.setClientToken(creds.clientToken);
276
- }
277
- opts.onEvent?.({ kind: "complete", payload: connection });
278
- resolve(
279
- (0, import_platform_protocol.ok)({
280
- dispose: () => {
281
- handle.dispose();
282
- removeSlot(slotId);
283
- }
284
- })
285
- );
286
- }
287
- });
288
- });
289
- } catch (e) {
290
- return (0, import_platform_protocol.err)({
291
- message: e instanceof Error ? e.message : "Connect failed"
292
- });
293
- }
1016
+ return;
294
1017
  }
295
- async function setupAuth(opts) {
296
- const clientToken = core.context.clientToken;
297
- if (!clientToken) {
298
- return (0, import_platform_protocol.err)({
299
- kind: "configurationError",
300
- message: 'No clientToken in context \u2014 call getConnection() first and ensure it resolved with status "connectionRequired".'
301
- });
1018
+ setTransport(session.transport);
1019
+ session.ready.then((handle) => {
1020
+ if (disposed) {
1021
+ handle.dispose();
1022
+ return;
302
1023
  }
303
- const { privateKey, publicKey } = (0, import_platform_sdk_core.generateKeyPair)();
304
- const channelId = `auth-${Date.now()}`;
305
- const url = (0, import_platform_sdk_core.buildFrameUrl)(
306
- import_platform_sdk_core.FRAME_PATHS.auth,
307
- { clientToken, channelId, publicKey },
308
- { frameBaseUrl }
309
- );
310
- try {
311
- const { promise } = createManagedFrame({ url, channelId, hidden: false });
312
- const { handle, slotId } = await promise;
313
- return new Promise((resolve) => {
314
- handle.onMessage((msg) => {
315
- if (msg.kind === "ready") {
316
- opts.onEvent?.({ kind: "ready" });
317
- return;
318
- }
319
- if (msg.kind === "error") {
320
- const payload = msg.payload;
321
- opts.onEvent?.({ kind: "error", payload });
322
- handle.dispose();
323
- removeSlot(slotId);
324
- resolve((0, import_platform_protocol.err)({ kind: "genericError", message: "Auth frame error" }));
325
- return;
326
- }
327
- if (msg.kind === "complete") {
328
- const connection = msg.payload;
329
- if (connection.status === import_platform_protocol.ConnectionStatus.active) {
330
- const creds = (0, import_platform_sdk_core.decryptCredentials)(connection.credentials, privateKey);
331
- core.context.setAccessToken(creds.accessToken);
332
- core.context.setClientToken(creds.clientToken);
333
- }
334
- if (connection.status === import_platform_protocol.ConnectionStatus.active || connection.status === import_platform_protocol.ConnectionStatus.termsAcceptanceRequired) {
335
- opts.onEvent?.({ kind: "complete", payload: connection });
336
- }
337
- resolve(
338
- (0, import_platform_protocol.ok)({
339
- dispose: () => {
340
- handle.dispose();
341
- removeSlot(slotId);
342
- }
343
- })
344
- );
345
- }
346
- });
347
- });
348
- } catch (e) {
349
- return (0, import_platform_protocol.err)({
350
- kind: "genericError",
351
- message: e instanceof Error ? e.message : "Auth setup failed"
352
- });
1024
+ handleRef.current = handle;
1025
+ handle.onEvent((event) => onEventRef.current?.(event));
1026
+ applyReactiveProps(spec, reactiveKeys, propsRef.current, appliedRef.current, handle);
1027
+ }).catch((e) => {
1028
+ if (!disposed) {
1029
+ onEventRef.current?.(
1030
+ spec.errorEvent(e instanceof Error ? e.message : "Frame handshake failed")
1031
+ );
353
1032
  }
1033
+ });
1034
+ return () => {
1035
+ disposed = true;
1036
+ handleRef.current = null;
1037
+ session.dispose();
1038
+ setTransport(null);
1039
+ };
1040
+ }, [mountKey, spec, sessionToken, core, frameBaseUrl]);
1041
+ (0, import_react3.useEffect)(() => {
1042
+ const handle = handleRef.current;
1043
+ if (!handle)
1044
+ return;
1045
+ applyReactiveProps(spec, reactiveKeys, propsRef.current, appliedRef.current, handle);
1046
+ }, [liveKey]);
1047
+ if (spec.hidden) {
1048
+ return transport ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MoonPayFrame, { transport, hidden: true }) : null;
1049
+ }
1050
+ const resolvedStyle = { ...defaultStyle, ...style };
1051
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style: resolvedStyle, children: transport ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MoonPayFrame, { transport }) : null });
1052
+ }
1053
+
1054
+ // src/components/add-card.tsx
1055
+ var import_jsx_runtime4 = require("react/jsx-runtime");
1056
+ function MoonPayAddCard({ onEvent, style }) {
1057
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1058
+ MoonPayFrameView,
1059
+ {
1060
+ spec: addCardSpec,
1061
+ props: {},
1062
+ style,
1063
+ defaultStyle: { flex: 1 },
1064
+ onEvent
354
1065
  }
355
- async function setupWidget(opts) {
356
- const channelId = `widget-${Date.now()}`;
357
- const url = (0, import_platform_sdk_core.buildFrameUrl)(
358
- import_platform_sdk_core.FRAME_PATHS.widget,
359
- {
360
- flow: "buy",
361
- clientToken: core.context.clientToken,
362
- quoteSignature: opts.quote,
363
- channelId
364
- },
365
- { frameBaseUrl }
366
- );
367
- try {
368
- const { promise } = createManagedFrame({ url, channelId, hidden: false });
369
- const { handle, slotId } = await promise;
370
- handle.onMessage((msg) => {
371
- switch (msg.kind) {
372
- case "ready":
373
- opts.onEvent?.({ kind: "ready" });
374
- break;
375
- case "transactionCreated":
376
- opts.onEvent?.({
377
- kind: "transactionCreated",
378
- payload: msg.payload
379
- });
380
- break;
381
- case "complete":
382
- opts.onEvent?.({
383
- kind: "complete",
384
- payload: msg.payload
385
- });
386
- break;
387
- case "error": {
388
- const payload = msg.payload;
389
- opts.onEvent?.({
390
- kind: "error",
391
- payload: { code: payload.code, message: payload.message }
392
- });
393
- break;
394
- }
395
- case "close":
396
- opts.onEvent?.({ kind: "close" });
397
- break;
398
- }
399
- });
400
- return (0, import_platform_protocol.ok)({
401
- dispose: () => {
402
- handle.dispose();
403
- removeSlot(slotId);
404
- }
405
- });
406
- } catch (e) {
407
- return (0, import_platform_protocol.err)({
408
- kind: "genericError",
409
- message: e instanceof Error ? e.message : "Widget setup failed"
410
- });
411
- }
1066
+ );
1067
+ }
1068
+
1069
+ // src/components/apple-pay-button.tsx
1070
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1071
+ function MoonPayApplePayButton({
1072
+ quote,
1073
+ onEvent,
1074
+ style
1075
+ }) {
1076
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1077
+ MoonPayFrameView,
1078
+ {
1079
+ spec: applePaySpec,
1080
+ props: { quote },
1081
+ style,
1082
+ defaultStyle: { height: 48 },
1083
+ onEvent
412
1084
  }
413
- async function setupApplePay(opts) {
414
- const channelId = `applepay-${Date.now()}`;
415
- const url = (0, import_platform_sdk_core.buildFrameUrl)(
416
- import_platform_sdk_core.FRAME_PATHS.applePay,
417
- {
418
- clientToken: core.context.clientToken,
419
- signature: opts.quote,
420
- channelId
421
- },
422
- { frameBaseUrl }
423
- );
424
- try {
425
- const { promise } = createManagedFrame({ url, channelId, hidden: false });
426
- const { handle, slotId } = await promise;
427
- const setQuote = (signature) => {
428
- handle.sendMessage({
429
- version: 2,
430
- meta: { channelId },
431
- kind: "setQuote",
432
- payload: { quote: { signature } }
433
- });
434
- };
435
- handle.onMessage((msg) => {
436
- switch (msg.kind) {
437
- case "ready":
438
- opts.onEvent?.({ kind: "ready" });
439
- break;
440
- case "complete":
441
- opts.onEvent?.({
442
- kind: "complete",
443
- payload: msg.payload
444
- });
445
- break;
446
- case "error": {
447
- const payload = msg.payload;
448
- if (payload.code === "quoteExpired") {
449
- opts.onEvent?.({ kind: "quoteExpired", payload: { setQuote } });
450
- } else if (payload.code === "applePayUnavailable") {
451
- opts.onEvent?.({ kind: "unsupported" });
452
- } else {
453
- const kind = payload.code === "generic" ? "genericError" : payload.code;
454
- opts.onEvent?.({
455
- kind: "error",
456
- payload: { kind, message: payload.message }
457
- });
458
- }
459
- break;
460
- }
461
- }
462
- });
463
- return (0, import_platform_protocol.ok)({
464
- setQuote,
465
- dispose: () => {
466
- handle.dispose();
467
- removeSlot(slotId);
468
- }
469
- });
470
- } catch (e) {
471
- return (0, import_platform_protocol.err)({
472
- kind: "genericError",
473
- message: e instanceof Error ? e.message : "Apple Pay setup failed"
474
- });
475
- }
1085
+ );
1086
+ }
1087
+
1088
+ // src/components/auth.tsx
1089
+ var import_jsx_runtime6 = require("react/jsx-runtime");
1090
+ function MoonPayAuth({ onEvent, style }) {
1091
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1092
+ MoonPayFrameView,
1093
+ {
1094
+ spec: authSpec,
1095
+ props: {},
1096
+ style,
1097
+ defaultStyle: { flex: 1 },
1098
+ onEvent
476
1099
  }
477
- async function setupBuy(opts) {
478
- const channelId = `buy-${Date.now()}`;
479
- const url = (0, import_platform_sdk_core.buildFrameUrl)(
480
- import_platform_sdk_core.FRAME_PATHS.buy,
481
- {
482
- channelId,
483
- clientToken: core.context.clientToken,
484
- signature: opts.quote,
485
- ...opts.externalTransactionId && { externalTransactionId: opts.externalTransactionId }
486
- },
487
- { frameBaseUrl }
488
- );
489
- try {
490
- const { promise } = createManagedFrame({ url, channelId, hidden: true });
491
- const { handle, slotId } = await promise;
492
- const setQuote = (signature) => {
493
- handle.sendMessage({
494
- version: 2,
495
- meta: { channelId },
496
- kind: "setQuote",
497
- payload: { quote: { signature } }
498
- });
499
- };
500
- handle.onMessage((msg) => {
501
- switch (msg.kind) {
502
- case "ready":
503
- opts.onEvent?.({ kind: "ready" });
504
- break;
505
- case "complete":
506
- opts.onEvent?.({
507
- kind: "complete",
508
- payload: msg.payload
509
- });
510
- break;
511
- case "challenge":
512
- opts.onEvent?.({
513
- kind: "challenge",
514
- payload: msg.payload
515
- });
516
- break;
517
- case "error":
518
- opts.onEvent?.({
519
- kind: "error",
520
- payload: msg.payload
521
- });
522
- break;
523
- }
524
- });
525
- return (0, import_platform_protocol.ok)({
526
- setQuote,
527
- dispose: () => {
528
- handle.dispose();
529
- removeSlot(slotId);
530
- }
531
- });
532
- } catch (e) {
533
- return (0, import_platform_protocol.err)({
534
- kind: "genericError",
535
- message: e instanceof Error ? e.message : "Buy setup failed"
536
- });
537
- }
1100
+ );
1101
+ }
1102
+
1103
+ // src/components/buy-button.tsx
1104
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1105
+ function MoonPayBuyButton({ quote, onEvent, style }) {
1106
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1107
+ MoonPayFrameView,
1108
+ {
1109
+ spec: buyButtonSpec,
1110
+ props: { quote },
1111
+ style,
1112
+ defaultStyle: { height: 48 },
1113
+ onEvent
538
1114
  }
539
- async function setupBuyButton(opts) {
540
- const channelId = `buy-button-${Date.now()}`;
541
- const url = (0, import_platform_sdk_core.buildFrameUrl)(
542
- import_platform_sdk_core.FRAME_PATHS.buyButton,
543
- {
544
- channelId,
545
- clientToken: core.context.clientToken,
546
- signature: opts.quote
547
- },
548
- { frameBaseUrl }
549
- );
550
- try {
551
- const { promise } = createManagedFrame({ url, channelId, hidden: false });
552
- const { handle, slotId } = await promise;
553
- const setQuote = (signature) => {
554
- handle.sendMessage({
555
- version: 2,
556
- meta: { channelId },
557
- kind: "setQuote",
558
- payload: { quote: { signature } }
559
- });
560
- };
561
- handle.onMessage((msg) => {
562
- switch (msg.kind) {
563
- case "complete":
564
- opts.onEvent?.({
565
- kind: "complete",
566
- payload: msg.payload
567
- });
568
- break;
569
- case "challenge":
570
- opts.onEvent?.({
571
- kind: "challenge",
572
- payload: msg.payload
573
- });
574
- break;
575
- case "error":
576
- opts.onEvent?.({
577
- kind: "error",
578
- payload: msg.payload
579
- });
580
- break;
581
- }
582
- });
583
- return (0, import_platform_protocol.ok)({
584
- setQuote,
585
- dispose: () => {
586
- handle.dispose();
587
- removeSlot(slotId);
588
- }
589
- });
590
- } catch (e) {
591
- return (0, import_platform_protocol.err)({
592
- kind: "genericError",
593
- message: e instanceof Error ? e.message : "Buy button setup failed"
594
- });
595
- }
1115
+ );
1116
+ }
1117
+
1118
+ // src/components/buy-frame.tsx
1119
+ var import_jsx_runtime8 = require("react/jsx-runtime");
1120
+ function MoonPayBuyFrame({
1121
+ quote,
1122
+ externalTransactionId,
1123
+ onEvent
1124
+ }) {
1125
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1126
+ MoonPayFrameView,
1127
+ {
1128
+ spec: buySpec,
1129
+ props: { quote, externalTransactionId },
1130
+ defaultStyle: {},
1131
+ onEvent
596
1132
  }
597
- async function setupGooglePay(opts) {
598
- const channelId = `googlepay-${Date.now()}`;
599
- const url = (0, import_platform_sdk_core.buildFrameUrl)(
600
- import_platform_sdk_core.FRAME_PATHS.googlePay,
601
- {
602
- clientToken: core.context.clientToken,
603
- signature: opts.quote,
604
- channelId,
605
- ...opts.externalTransactionId && { externalTransactionId: opts.externalTransactionId }
606
- },
607
- { frameBaseUrl }
608
- );
609
- try {
610
- const { promise } = createManagedFrame({ url, channelId, hidden: false });
611
- const { handle, slotId } = await promise;
612
- const setQuote = (signature) => {
613
- handle.sendMessage({
614
- version: 2,
615
- meta: { channelId },
616
- kind: "setQuote",
617
- payload: { quote: { signature } }
618
- });
619
- };
620
- handle.onMessage((msg) => {
621
- switch (msg.kind) {
622
- case "ready":
623
- opts.onEvent?.({ kind: "ready" });
624
- break;
625
- case "complete":
626
- opts.onEvent?.({
627
- kind: "complete",
628
- payload: msg.payload
629
- });
630
- break;
631
- case "challenge":
632
- opts.onEvent?.({
633
- kind: "challenge",
634
- payload: msg.payload
635
- });
636
- break;
637
- case "error": {
638
- const payload = msg.payload;
639
- if (payload.code === "quoteExpired") {
640
- opts.onEvent?.({ kind: "quoteExpired", payload: { setQuote } });
641
- } else if (payload.code === "googlePayUnavailable") {
642
- opts.onEvent?.({ kind: "unsupported" });
643
- } else {
644
- const kind = payload.code === "generic" ? "genericError" : payload.code;
645
- opts.onEvent?.({
646
- kind: "error",
647
- payload: { kind, message: payload.message }
648
- });
649
- }
650
- break;
651
- }
652
- }
653
- });
654
- return (0, import_platform_protocol.ok)({
655
- setQuote,
656
- dispose: () => {
657
- handle.dispose();
658
- removeSlot(slotId);
659
- }
660
- });
661
- } catch (e) {
662
- return (0, import_platform_protocol.err)({
663
- kind: "genericError",
664
- message: e instanceof Error ? e.message : "Google Pay setup failed"
665
- });
666
- }
1133
+ );
1134
+ }
1135
+
1136
+ // src/components/challenge.tsx
1137
+ var import_jsx_runtime9 = require("react/jsx-runtime");
1138
+ function MoonPayChallenge({ url, onEvent, style }) {
1139
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1140
+ MoonPayFrameView,
1141
+ {
1142
+ spec: challengeSpec,
1143
+ props: { url },
1144
+ style,
1145
+ defaultStyle: { flex: 1 },
1146
+ onEvent
667
1147
  }
668
- async function resetConnection() {
669
- const channelId = `reset-${Date.now()}`;
670
- const url = (0, import_platform_sdk_core.buildFrameUrl)(import_platform_sdk_core.FRAME_PATHS.reset, { sessionToken, channelId }, { frameBaseUrl });
671
- try {
672
- const { promise } = createManagedFrame({
673
- url,
674
- channelId,
675
- hidden: true,
676
- handshakeTimeout: 5e3
677
- });
678
- const { handle, slotId } = await promise;
679
- return new Promise((resolve) => {
680
- const timeout = setTimeout(() => {
681
- handle.dispose();
682
- removeSlot(slotId);
683
- resolve((0, import_platform_protocol.ok)(void 0));
684
- }, 5e3);
685
- handle.onMessage((msg) => {
686
- if (msg.kind === "complete" || msg.kind === "error") {
687
- clearTimeout(timeout);
688
- handle.dispose();
689
- removeSlot(slotId);
690
- resolve((0, import_platform_protocol.ok)(void 0));
691
- }
692
- });
693
- });
694
- } catch {
695
- return (0, import_platform_protocol.ok)(void 0);
696
- }
1148
+ );
1149
+ }
1150
+
1151
+ // src/components/connect.tsx
1152
+ var import_jsx_runtime10 = require("react/jsx-runtime");
1153
+ function MoonPayConnect({ theme, onEvent, style }) {
1154
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1155
+ MoonPayFrameView,
1156
+ {
1157
+ spec: connectSpec,
1158
+ props: { theme },
1159
+ style,
1160
+ defaultStyle: { flex: 1 },
1161
+ onEvent
697
1162
  }
698
- async function setupChallenge(opts) {
699
- let url;
700
- try {
701
- url = new URL(opts.url);
702
- } catch {
703
- return (0, import_platform_protocol.err)({ kind: "configurationError", message: "Invalid challenge URL" });
704
- }
705
- let channelId = url.searchParams.get("channelId") ?? "";
706
- if (!channelId) {
707
- channelId = `challenge-${Date.now()}`;
708
- url.searchParams.set("channelId", channelId);
709
- }
710
- try {
711
- const { promise } = createManagedFrame({
712
- url: url.toString(),
713
- channelId,
714
- hidden: false
715
- });
716
- const { handle, slotId } = await promise;
717
- handle.onMessage((msg) => {
718
- switch (msg.kind) {
719
- case "ready":
720
- opts.onEvent?.({ kind: "ready" });
721
- break;
722
- case "complete":
723
- opts.onEvent?.({
724
- kind: "complete",
725
- payload: msg.payload
726
- });
727
- break;
728
- case "cancelled":
729
- opts.onEvent?.({
730
- kind: "cancelled",
731
- payload: msg.payload
732
- });
733
- break;
734
- case "error":
735
- opts.onEvent?.({
736
- kind: "error",
737
- payload: msg.payload
738
- });
739
- break;
740
- }
741
- });
742
- return (0, import_platform_protocol.ok)({
743
- dispose: () => {
744
- handle.dispose();
745
- removeSlot(slotId);
746
- }
747
- });
748
- } catch (e) {
749
- return (0, import_platform_protocol.err)({
750
- kind: "genericError",
751
- message: e instanceof Error ? e.message : "Challenge setup failed"
752
- });
753
- }
1163
+ );
1164
+ }
1165
+
1166
+ // src/components/connection-check.tsx
1167
+ var import_jsx_runtime11 = require("react/jsx-runtime");
1168
+ function MoonPayConnectionCheck({
1169
+ skipKyc,
1170
+ onEvent
1171
+ }) {
1172
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1173
+ MoonPayFrameView,
1174
+ {
1175
+ spec: connectionCheckSpec,
1176
+ props: { skipKyc },
1177
+ defaultStyle: {},
1178
+ onEvent
754
1179
  }
755
- async function setupAddCard(opts) {
756
- const channelId = `add-card-${Date.now()}`;
757
- const url = (0, import_platform_sdk_core.buildFrameUrl)(
758
- import_platform_sdk_core.FRAME_PATHS.addCard,
759
- { channelId, clientToken: core.context.clientToken },
760
- { frameBaseUrl }
761
- );
762
- try {
763
- const { promise } = createManagedFrame({ url, channelId, hidden: false });
764
- const { handle, slotId } = await promise;
765
- handle.onMessage((msg) => {
766
- switch (msg.kind) {
767
- case "complete":
768
- opts.onEvent?.({ kind: "complete", payload: msg.payload });
769
- break;
770
- case "error":
771
- opts.onEvent?.({
772
- kind: "error",
773
- payload: msg.payload
774
- });
775
- break;
776
- }
777
- });
778
- return (0, import_platform_protocol.ok)({
779
- dispose: () => {
780
- handle.dispose();
781
- removeSlot(slotId);
782
- }
783
- });
784
- } catch (e) {
785
- return (0, import_platform_protocol.err)({
786
- kind: "genericError",
787
- message: e instanceof Error ? e.message : "Add card setup failed"
788
- });
789
- }
1180
+ );
1181
+ }
1182
+
1183
+ // src/components/connection-reset.tsx
1184
+ var import_jsx_runtime12 = require("react/jsx-runtime");
1185
+ function MoonPayConnectionReset({ onEvent }) {
1186
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(MoonPayFrameView, { spec: connectionResetSpec, props: {}, defaultStyle: {}, onEvent });
1187
+ }
1188
+
1189
+ // src/components/google-pay-button.tsx
1190
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1191
+ function MoonPayGooglePayButton({
1192
+ quote,
1193
+ externalTransactionId,
1194
+ onEvent,
1195
+ style
1196
+ }) {
1197
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1198
+ MoonPayFrameView,
1199
+ {
1200
+ spec: googlePaySpec,
1201
+ props: { quote, externalTransactionId },
1202
+ style,
1203
+ defaultStyle: { height: 48 },
1204
+ onEvent
790
1205
  }
791
- return {
792
- getConnection,
793
- connect,
794
- setupAuth,
795
- getPaymentMethods: () => core.getPaymentMethods(),
796
- getQuote: (params) => core.getQuote(params),
797
- listTransactions: (params) => core.listTransactions(params),
798
- getTransaction: (id) => core.getTransaction(id),
799
- setupWidget,
800
- setupApplePay,
801
- setupBuy,
802
- setupBuyButton,
803
- setupGooglePay,
804
- deletePaymentMethod: (id) => core.deletePaymentMethod(id),
805
- resetConnection,
806
- setupChallenge,
807
- setupAddCard,
808
- createIdentity: (body) => core.createIdentity(body),
809
- getIdentity: (id) => core.getIdentity(id),
810
- updateIdentity: (id, body) => core.updateIdentity(id, body),
811
- verifyIdentity: (id) => core.verifyIdentity(id),
812
- getIdentityUploadUrl: (id, body) => core.getIdentityUploadUrl(id, body),
813
- submitIdentityFiles: (id, body) => core.submitIdentityFiles(id, body)
814
- };
815
- }, [sessionToken, frameBaseUrl, core, addSlot, removeSlot]);
816
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(MoonPayContext.Provider, { value: { client }, children: [
817
- children,
818
- frameSlots.map((slot) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(MoonPayFrame, { transport: slot.transport, hidden: slot.hidden }, slot.id))
819
- ] });
1206
+ );
820
1207
  }
821
- function useMoonPay() {
822
- const ctx = (0, import_react2.useContext)(MoonPayContext);
823
- if (!ctx) {
824
- throw new Error("useMoonPay must be used within a <MoonPayProvider>");
825
- }
826
- return ctx;
1208
+
1209
+ // src/components/widget.tsx
1210
+ var import_jsx_runtime14 = require("react/jsx-runtime");
1211
+ function MoonPayWidget({ quote, onEvent, style }) {
1212
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1213
+ MoonPayFrameView,
1214
+ {
1215
+ spec: widgetSpec,
1216
+ props: { quote },
1217
+ style,
1218
+ defaultStyle: { flex: 1 },
1219
+ onEvent
1220
+ }
1221
+ );
827
1222
  }
828
1223
  // Annotate the CommonJS export names for ESM import in node:
829
1224
  0 && (module.exports = {
1225
+ ConnectionStatus,
1226
+ MoonPayAddCard,
1227
+ MoonPayApplePayButton,
1228
+ MoonPayAuth,
1229
+ MoonPayBuyButton,
1230
+ MoonPayBuyFrame,
1231
+ MoonPayChallenge,
1232
+ MoonPayConnect,
1233
+ MoonPayConnectionCheck,
1234
+ MoonPayConnectionReset,
830
1235
  MoonPayFrame,
1236
+ MoonPayGooglePayButton,
831
1237
  MoonPayProvider,
1238
+ MoonPayWidget,
832
1239
  WebViewTransport,
833
1240
  useMoonPay
834
1241
  });