@alien_org/react 0.0.11-beta

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 ADDED
@@ -0,0 +1,546 @@
1
+ let _alien_org_bridge = require("@alien_org/bridge");
2
+ let _alien_org_contract = require("@alien_org/contract");
3
+ let react = require("react");
4
+ let react_jsx_runtime = require("react/jsx-runtime");
5
+
6
+ //#region src/context.tsx
7
+ const AlienContext = (0, react.createContext)(null);
8
+ /**
9
+ * Provider component that initializes the Alien miniapp context.
10
+ * Must wrap your app to use Alien hooks.
11
+ *
12
+ * @example
13
+ * ```tsx
14
+ * import { AlienProvider } from '@alien_org/react';
15
+ *
16
+ * function App() {
17
+ * return (
18
+ * <AlienProvider>
19
+ * <MyMiniapp />
20
+ * </AlienProvider>
21
+ * );
22
+ * }
23
+ * ```
24
+ */
25
+ function AlienProvider({ children }) {
26
+ const value = (0, react.useMemo)(() => {
27
+ const launchParams = (0, _alien_org_bridge.getLaunchParams)();
28
+ return {
29
+ authToken: launchParams?.authToken,
30
+ contractVersion: launchParams?.contractVersion,
31
+ isBridgeAvailable: (0, _alien_org_bridge.isBridgeAvailable)()
32
+ };
33
+ }, []);
34
+ (0, react.useEffect)(() => {
35
+ if (!value.isBridgeAvailable) console.warn("[@alien_org/react] Bridge is not available. Running in dev mode? The SDK will handle errors gracefully, but bridge communication will not work.");
36
+ }, [value.isBridgeAvailable]);
37
+ (0, react.useEffect)(() => {
38
+ if (value.isBridgeAvailable) (0, _alien_org_bridge.send)("app:ready", {});
39
+ }, [value.isBridgeAvailable]);
40
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AlienContext.Provider, {
41
+ value,
42
+ children
43
+ });
44
+ }
45
+
46
+ //#endregion
47
+ //#region src/errors.ts
48
+ /**
49
+ * Base class for all React SDK errors.
50
+ */
51
+ var ReactSDKError = class extends Error {
52
+ constructor(message) {
53
+ super(message);
54
+ this.name = "ReactSDKError";
55
+ }
56
+ };
57
+ /**
58
+ * Error thrown when a method is not supported by the current contract version.
59
+ */
60
+ var MethodNotSupportedError = class extends ReactSDKError {
61
+ method;
62
+ contractVersion;
63
+ minVersion;
64
+ constructor(method, contractVersion, minVersion) {
65
+ const message = minVersion ? `Method "${method}" requires version ${minVersion}, but host provides ${contractVersion ?? "unknown"}` : `Method "${method}" is not supported`;
66
+ super(message);
67
+ this.name = "MethodNotSupportedError";
68
+ this.method = method;
69
+ this.contractVersion = contractVersion;
70
+ this.minVersion = minVersion;
71
+ }
72
+ };
73
+
74
+ //#endregion
75
+ //#region src/hooks/useAlien.ts
76
+ /**
77
+ * Hook to access the Alien context.
78
+ * Must be used within an AlienProvider.
79
+ *
80
+ * For additional launch params (platform, startParam, hostAppVersion),
81
+ * use the `useLaunchParams` hook.
82
+ *
83
+ * @example
84
+ * ```tsx
85
+ * const { authToken, contractVersion, isBridgeAvailable } = useAlien();
86
+ * ```
87
+ */
88
+ function useAlien() {
89
+ const context = (0, react.useContext)(AlienContext);
90
+ if (!context) throw new Error("useAlien must be used within an AlienProvider");
91
+ return context;
92
+ }
93
+
94
+ //#endregion
95
+ //#region src/hooks/useEvent.ts
96
+ /**
97
+ * Hook to subscribe to bridge events.
98
+ * Automatically handles subscription cleanup on unmount.
99
+ *
100
+ * @param event - The event name to subscribe to.
101
+ * @param callback - The callback to invoke when the event is received.
102
+ *
103
+ * @example
104
+ * ```tsx
105
+ * import { useEvent } from '@alien_org/react';
106
+ *
107
+ * function MyComponent() {
108
+ * useEvent('miniapp:close', () => {
109
+ * // Cleanup before miniapp closes
110
+ * saveState();
111
+ * });
112
+ *
113
+ * useEvent('host.back.button:clicked', () => {
114
+ * // Handle back button press
115
+ * navigateBack();
116
+ * });
117
+ *
118
+ * return <div>Listening for events...</div>;
119
+ * }
120
+ * ```
121
+ */
122
+ function useEvent(event, callback) {
123
+ const callbackRef = (0, react.useRef)(callback);
124
+ callbackRef.current = callback;
125
+ const { isBridgeAvailable: isBridgeAvailable$1 } = useAlien();
126
+ (0, react.useEffect)(() => {
127
+ if (!isBridgeAvailable$1) {
128
+ console.warn("[@alien_org/react] Bridge is not available. Event listener will not be set up. Running in dev mode?");
129
+ return;
130
+ }
131
+ const handler = (payload) => {
132
+ callbackRef.current(payload);
133
+ };
134
+ try {
135
+ return (0, _alien_org_bridge.on)(event, handler);
136
+ } catch (error) {
137
+ console.warn("[@alien_org/react] Failed to set up event listener:", error instanceof Error ? error.message : String(error));
138
+ return;
139
+ }
140
+ }, [event, isBridgeAvailable$1]);
141
+ }
142
+
143
+ //#endregion
144
+ //#region src/hooks/useIsMethodSupported.ts
145
+ /**
146
+ * Hook to check if a method is supported by the host app's contract version.
147
+ *
148
+ * @param method - The method name to check.
149
+ * @returns Object with `supported`, `contractVersion`, and `minVersion`.
150
+ *
151
+ * @example
152
+ * ```tsx
153
+ * import { useMethodSupported } from '@alien_org/react';
154
+ *
155
+ * function MyComponent() {
156
+ * const { supported, minVersion } = useMethodSupported('payment:request');
157
+ *
158
+ * if (!supported) {
159
+ * return <div>This feature requires version {minVersion}</div>;
160
+ * }
161
+ *
162
+ * return <div>Feature available!</div>;
163
+ * }
164
+ * ```
165
+ */
166
+ function useIsMethodSupported(method) {
167
+ const { contractVersion } = useAlien();
168
+ return {
169
+ supported: contractVersion ? (0, _alien_org_contract.isMethodSupported)(method, contractVersion) : true,
170
+ contractVersion,
171
+ minVersion: (0, _alien_org_contract.getMethodMinVersion)(method)
172
+ };
173
+ }
174
+
175
+ //#endregion
176
+ //#region src/hooks/useLaunchParams.ts
177
+ /**
178
+ * Hook to get launch params.
179
+ * Returns undefined if params unavailable (use mockLaunchParamsForDev in dev).
180
+ *
181
+ * @example
182
+ * ```tsx
183
+ * import { useLaunchParams } from '@alien_org/react';
184
+ *
185
+ * function MyComponent() {
186
+ * const launchParams = useLaunchParams();
187
+ *
188
+ * if (!launchParams) {
189
+ * return <div>Running outside Alien App</div>;
190
+ * }
191
+ *
192
+ * return <div>Platform: {launchParams.platform}</div>;
193
+ * }
194
+ * ```
195
+ */
196
+ function useLaunchParams() {
197
+ return (0, react.useMemo)(() => (0, _alien_org_bridge.getLaunchParams)(), []);
198
+ }
199
+
200
+ //#endregion
201
+ //#region src/hooks/useMethod.ts
202
+ /**
203
+ * Hook for making bridge requests with loading/error state management.
204
+ *
205
+ * @param method - The method name to call.
206
+ * @param responseEvent - The event name to listen for the response.
207
+ * @param options - Hook options including version checking.
208
+ * @returns Object with `execute`, `reset`, `data`, `error`, `isLoading`, and `supported`.
209
+ *
210
+ * @example
211
+ * ```tsx
212
+ * import { useMethod } from '@alien_org/react';
213
+ *
214
+ * function PayButton() {
215
+ * const { execute, data, error, isLoading, supported } = useMethod(
216
+ * 'payment:request',
217
+ * 'payment:response',
218
+ * );
219
+ *
220
+ * if (!supported) {
221
+ * return <div>This feature is not available</div>;
222
+ * }
223
+ *
224
+ * const handlePay = async () => {
225
+ * // Errors are automatically set in the `error` state - no try/catch needed!
226
+ * const { error, data } = await execute({
227
+ * recipient: 'wallet-123',
228
+ * amount: '100',
229
+ * token: 'SOL',
230
+ * network: 'solana',
231
+ * invoice: 'inv-123',
232
+ * });
233
+ * if (error) {
234
+ * console.error(error);
235
+ * return;
236
+ * }
237
+ * if (data) {
238
+ * console.log('Success:', data);
239
+ * }
240
+ * };
241
+ *
242
+ * if (isLoading) return <button disabled>Loading...</button>;
243
+ * if (error) return <div>Error: {error.message}</div>;
244
+ * if (data) return <div>Payment complete!</div>;
245
+ *
246
+ * return <button onClick={handlePay}>Pay</button>;
247
+ * }
248
+ * ```
249
+ */
250
+ function useMethod(method, responseEvent, options = {}) {
251
+ const { checkVersion = true } = options;
252
+ const { contractVersion, isBridgeAvailable: isBridgeAvailable$1 } = useAlien();
253
+ const [state, setState] = (0, react.useState)({
254
+ data: void 0,
255
+ error: void 0,
256
+ isLoading: false
257
+ });
258
+ const supported = contractVersion ? (0, _alien_org_contract.isMethodSupported)(method, contractVersion) : true;
259
+ const execute = (0, react.useCallback)(async (params, requestOptions) => {
260
+ if (!isBridgeAvailable$1) {
261
+ const error = /* @__PURE__ */ new Error("Bridge is not available. Running in dev mode? Bridge communication will not work.");
262
+ console.warn("[@alien_org/react]", error.message);
263
+ setState({
264
+ data: void 0,
265
+ error,
266
+ isLoading: false
267
+ });
268
+ return {
269
+ data: void 0,
270
+ error
271
+ };
272
+ }
273
+ if (checkVersion) {
274
+ if (contractVersion && !(0, _alien_org_contract.isMethodSupported)(method, contractVersion)) {
275
+ const error = new MethodNotSupportedError(method, contractVersion, (0, _alien_org_contract.getMethodMinVersion)(method));
276
+ setState({
277
+ data: void 0,
278
+ error,
279
+ isLoading: false
280
+ });
281
+ return {
282
+ data: void 0,
283
+ error
284
+ };
285
+ }
286
+ }
287
+ setState({
288
+ data: void 0,
289
+ error: void 0,
290
+ isLoading: true
291
+ });
292
+ try {
293
+ const response = await (0, _alien_org_bridge.request)(method, params, responseEvent, requestOptions);
294
+ setState({
295
+ data: response,
296
+ error: void 0,
297
+ isLoading: false
298
+ });
299
+ return {
300
+ data: response,
301
+ error: void 0
302
+ };
303
+ } catch (err) {
304
+ if (err instanceof _alien_org_bridge.BridgeError) {
305
+ console.warn("[@alien_org/react] Bridge error:", err.message);
306
+ setState({
307
+ data: void 0,
308
+ error: err,
309
+ isLoading: false
310
+ });
311
+ return {
312
+ data: void 0,
313
+ error: err
314
+ };
315
+ }
316
+ const error = err instanceof Error ? err : new Error(String(err));
317
+ setState({
318
+ data: void 0,
319
+ error,
320
+ isLoading: false
321
+ });
322
+ return {
323
+ data: void 0,
324
+ error
325
+ };
326
+ }
327
+ }, [
328
+ method,
329
+ responseEvent,
330
+ checkVersion,
331
+ contractVersion,
332
+ isBridgeAvailable$1
333
+ ]);
334
+ const reset = (0, react.useCallback)(() => {
335
+ setState({
336
+ data: void 0,
337
+ error: void 0,
338
+ isLoading: false
339
+ });
340
+ }, []);
341
+ return (0, react.useMemo)(() => ({
342
+ ...state,
343
+ execute,
344
+ reset,
345
+ supported
346
+ }), [
347
+ state,
348
+ execute,
349
+ reset,
350
+ supported
351
+ ]);
352
+ }
353
+
354
+ //#endregion
355
+ //#region src/hooks/usePayment.ts
356
+ /**
357
+ * Hook for handling payments with full state management.
358
+ *
359
+ * Provides an easy-to-use interface for initiating payments and reacting
360
+ * to status changes. Automatically handles loading states, errors, and
361
+ * version checking.
362
+ *
363
+ * @param options - Optional configuration and callbacks.
364
+ * @returns Payment state and methods.
365
+ *
366
+ * @example
367
+ * ```tsx
368
+ * import { usePayment } from '@alien_org/react';
369
+ *
370
+ * function BuyButton({ orderId }: { orderId: string }) {
371
+ * const {
372
+ * pay,
373
+ * isLoading,
374
+ * isPaid,
375
+ * txHash,
376
+ * error,
377
+ * } = usePayment({
378
+ * onPaid: (txHash) => console.log('Paid!', txHash),
379
+ * onCancelled: () => console.log('Cancelled'),
380
+ * onFailed: (code) => console.log('Failed:', code),
381
+ * });
382
+ *
383
+ * const handleBuy = () => pay({
384
+ * recipient: 'wallet-address',
385
+ * amount: '1000000',
386
+ * token: 'SOL',
387
+ * network: 'solana',
388
+ * invoice: orderId,
389
+ * title: 'Premium Plan',
390
+ * });
391
+ *
392
+ * if (isPaid) return <div>Thank you! TX: {txHash}</div>;
393
+ *
394
+ * return (
395
+ * <button onClick={handleBuy} disabled={isLoading}>
396
+ * {isLoading ? 'Processing...' : 'Buy Now'}
397
+ * </button>
398
+ * );
399
+ * }
400
+ * ```
401
+ */
402
+ function usePayment(options = {}) {
403
+ const { timeout = 12e4, onPaid, onCancelled, onFailed, onStatusChange } = options;
404
+ const { contractVersion, isBridgeAvailable: isBridgeAvailable$1 } = useAlien();
405
+ const callbacksRef = (0, react.useRef)({
406
+ onPaid,
407
+ onCancelled,
408
+ onFailed,
409
+ onStatusChange
410
+ });
411
+ callbacksRef.current = {
412
+ onPaid,
413
+ onCancelled,
414
+ onFailed,
415
+ onStatusChange
416
+ };
417
+ const [state, setState] = (0, react.useState)({ status: "idle" });
418
+ const supported = contractVersion ? (0, _alien_org_contract.isMethodSupported)("payment:request", contractVersion) : true;
419
+ const updateState = (0, react.useCallback)((newState) => {
420
+ setState(newState);
421
+ callbacksRef.current.onStatusChange?.(newState.status);
422
+ }, []);
423
+ const pay = (0, react.useCallback)(async (params) => {
424
+ if (!isBridgeAvailable$1) {
425
+ const error = /* @__PURE__ */ new Error("Bridge is not available. Running in dev mode?");
426
+ console.warn("[@alien_org/react]", error.message);
427
+ const result = {
428
+ status: "failed",
429
+ errorCode: "unknown",
430
+ error
431
+ };
432
+ updateState(result);
433
+ callbacksRef.current.onFailed?.("unknown", error);
434
+ return result;
435
+ }
436
+ if (contractVersion && !(0, _alien_org_contract.isMethodSupported)("payment:request", contractVersion)) {
437
+ const error = new MethodNotSupportedError("payment:request", contractVersion, (0, _alien_org_contract.getMethodMinVersion)("payment:request"));
438
+ const result = {
439
+ status: "failed",
440
+ errorCode: "unknown",
441
+ error
442
+ };
443
+ updateState(result);
444
+ callbacksRef.current.onFailed?.("unknown", error);
445
+ return result;
446
+ }
447
+ updateState({ status: "loading" });
448
+ try {
449
+ const response = await (0, _alien_org_bridge.request)("payment:request", params, "payment:response", { timeout });
450
+ if (response.status === "paid") {
451
+ const txHash = response.txHash ?? "";
452
+ const result$1 = {
453
+ status: "paid",
454
+ txHash
455
+ };
456
+ updateState(result$1);
457
+ callbacksRef.current.onPaid?.(txHash);
458
+ return result$1;
459
+ }
460
+ if (response.status === "cancelled") {
461
+ const result$1 = { status: "cancelled" };
462
+ updateState(result$1);
463
+ callbacksRef.current.onCancelled?.();
464
+ return result$1;
465
+ }
466
+ const errorCode = response.errorCode ?? "unknown";
467
+ const result = {
468
+ status: "failed",
469
+ errorCode
470
+ };
471
+ updateState(result);
472
+ callbacksRef.current.onFailed?.(errorCode);
473
+ return result;
474
+ } catch (err) {
475
+ const error = err instanceof Error ? err : new Error(String(err));
476
+ if (err instanceof _alien_org_bridge.BridgeError) console.warn("[@alien_org/react] Bridge error:", err.message);
477
+ const result = {
478
+ status: "failed",
479
+ errorCode: "unknown",
480
+ error
481
+ };
482
+ updateState(result);
483
+ callbacksRef.current.onFailed?.("unknown", error);
484
+ return result;
485
+ }
486
+ }, [
487
+ isBridgeAvailable$1,
488
+ contractVersion,
489
+ timeout,
490
+ updateState
491
+ ]);
492
+ const reset = (0, react.useCallback)(() => {
493
+ updateState({ status: "idle" });
494
+ }, [updateState]);
495
+ return (0, react.useMemo)(() => ({
496
+ status: state.status,
497
+ isLoading: state.status === "loading",
498
+ isPaid: state.status === "paid",
499
+ isCancelled: state.status === "cancelled",
500
+ isFailed: state.status === "failed",
501
+ txHash: state.txHash,
502
+ errorCode: state.errorCode,
503
+ error: state.error,
504
+ pay,
505
+ reset,
506
+ supported
507
+ }), [
508
+ state,
509
+ pay,
510
+ reset,
511
+ supported
512
+ ]);
513
+ }
514
+
515
+ //#endregion
516
+ exports.AlienProvider = AlienProvider;
517
+ exports.BridgeError = _alien_org_bridge.BridgeError;
518
+ exports.BridgeTimeoutError = _alien_org_bridge.BridgeTimeoutError;
519
+ exports.BridgeUnavailableError = _alien_org_bridge.BridgeUnavailableError;
520
+ exports.BridgeWindowUnavailableError = _alien_org_bridge.BridgeWindowUnavailableError;
521
+ exports.MethodNotSupportedError = MethodNotSupportedError;
522
+ exports.ReactSDKError = ReactSDKError;
523
+ Object.defineProperty(exports, 'getMethodMinVersion', {
524
+ enumerable: true,
525
+ get: function () {
526
+ return _alien_org_contract.getMethodMinVersion;
527
+ }
528
+ });
529
+ Object.defineProperty(exports, 'isMethodSupported', {
530
+ enumerable: true,
531
+ get: function () {
532
+ return _alien_org_contract.isMethodSupported;
533
+ }
534
+ });
535
+ Object.defineProperty(exports, 'send', {
536
+ enumerable: true,
537
+ get: function () {
538
+ return _alien_org_bridge.send;
539
+ }
540
+ });
541
+ exports.useAlien = useAlien;
542
+ exports.useEvent = useEvent;
543
+ exports.useIsMethodSupported = useIsMethodSupported;
544
+ exports.useLaunchParams = useLaunchParams;
545
+ exports.useMethod = useMethod;
546
+ exports.usePayment = usePayment;