@alien_org/react 0.1.2 → 0.1.4
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 +79 -0
- package/dist/index.d.cts +177 -27
- package/dist/index.d.mts +177 -27
- package/dist/index.mjs +79 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -91,6 +91,84 @@ function useAlien() {
|
|
|
91
91
|
return context;
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
//#endregion
|
|
95
|
+
//#region src/hooks/useClipboard.ts
|
|
96
|
+
/**
|
|
97
|
+
* Hook for clipboard operations.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```tsx
|
|
101
|
+
* function ClipboardDemo() {
|
|
102
|
+
* const { writeText, readText, isReading, errorCode, supported } = useClipboard();
|
|
103
|
+
*
|
|
104
|
+
* if (!supported) return null;
|
|
105
|
+
*
|
|
106
|
+
* return (
|
|
107
|
+
* <>
|
|
108
|
+
* <button onClick={() => writeText('Hello!')}>Copy</button>
|
|
109
|
+
* <button
|
|
110
|
+
* onClick={async () => {
|
|
111
|
+
* const text = await readText();
|
|
112
|
+
* if (text !== null) console.log('Pasted:', text);
|
|
113
|
+
* }}
|
|
114
|
+
* disabled={isReading}
|
|
115
|
+
* >
|
|
116
|
+
* Paste
|
|
117
|
+
* </button>
|
|
118
|
+
* {errorCode && <span>Error: {errorCode}</span>}
|
|
119
|
+
* </>
|
|
120
|
+
* );
|
|
121
|
+
* }
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
124
|
+
function useClipboard(options = {}) {
|
|
125
|
+
const { timeout = 5e3 } = options;
|
|
126
|
+
const { contractVersion, isBridgeAvailable: isBridgeAvailable$1 } = useAlien();
|
|
127
|
+
const [isReading, setIsReading] = (0, react.useState)(false);
|
|
128
|
+
const [errorCode, setErrorCode] = (0, react.useState)(null);
|
|
129
|
+
const supported = contractVersion ? (0, _alien_org_contract.isMethodSupported)("clipboard:write", contractVersion) && (0, _alien_org_contract.isMethodSupported)("clipboard:read", contractVersion) : true;
|
|
130
|
+
const writeText = (0, react.useCallback)((text) => {
|
|
131
|
+
if (!isBridgeAvailable$1) return;
|
|
132
|
+
if (contractVersion && !(0, _alien_org_contract.isMethodSupported)("clipboard:write", contractVersion)) return;
|
|
133
|
+
(0, _alien_org_bridge.send)("clipboard:write", { text });
|
|
134
|
+
}, [isBridgeAvailable$1, contractVersion]);
|
|
135
|
+
const readText = (0, react.useCallback)(async () => {
|
|
136
|
+
if (!isBridgeAvailable$1) return null;
|
|
137
|
+
if (contractVersion && !(0, _alien_org_contract.isMethodSupported)("clipboard:read", contractVersion)) return null;
|
|
138
|
+
setIsReading(true);
|
|
139
|
+
setErrorCode(null);
|
|
140
|
+
try {
|
|
141
|
+
const response = await (0, _alien_org_bridge.request)("clipboard:read", {}, "clipboard:response", { timeout });
|
|
142
|
+
if (response.errorCode) {
|
|
143
|
+
setErrorCode(response.errorCode);
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
return response.text;
|
|
147
|
+
} catch {
|
|
148
|
+
return null;
|
|
149
|
+
} finally {
|
|
150
|
+
setIsReading(false);
|
|
151
|
+
}
|
|
152
|
+
}, [
|
|
153
|
+
isBridgeAvailable$1,
|
|
154
|
+
contractVersion,
|
|
155
|
+
timeout
|
|
156
|
+
]);
|
|
157
|
+
return (0, react.useMemo)(() => ({
|
|
158
|
+
writeText,
|
|
159
|
+
readText,
|
|
160
|
+
isReading,
|
|
161
|
+
errorCode,
|
|
162
|
+
supported
|
|
163
|
+
}), [
|
|
164
|
+
writeText,
|
|
165
|
+
readText,
|
|
166
|
+
isReading,
|
|
167
|
+
errorCode,
|
|
168
|
+
supported
|
|
169
|
+
]);
|
|
170
|
+
}
|
|
171
|
+
|
|
94
172
|
//#endregion
|
|
95
173
|
//#region src/hooks/useEvent.ts
|
|
96
174
|
/**
|
|
@@ -539,6 +617,7 @@ Object.defineProperty(exports, 'send', {
|
|
|
539
617
|
}
|
|
540
618
|
});
|
|
541
619
|
exports.useAlien = useAlien;
|
|
620
|
+
exports.useClipboard = useClipboard;
|
|
542
621
|
exports.useEvent = useEvent;
|
|
543
622
|
exports.useIsMethodSupported = useIsMethodSupported;
|
|
544
623
|
exports.useLaunchParams = useLaunchParams;
|
package/dist/index.d.cts
CHANGED
|
@@ -33,6 +33,41 @@ type UnionKeys<T> = T extends T ? keyof T : never;
|
|
|
33
33
|
* // Empty = {}
|
|
34
34
|
*/
|
|
35
35
|
type Empty = Record<string, never>;
|
|
36
|
+
/**
|
|
37
|
+
* Client-side payment error codes (pre-broadcast failures).
|
|
38
|
+
* Returned when `status` is `'failed'` in `payment:response`.
|
|
39
|
+
* These errors occur before transaction broadcast, so no webhook is sent.
|
|
40
|
+
* @since 0.1.1
|
|
41
|
+
* @schema
|
|
42
|
+
*/
|
|
43
|
+
type PaymentErrorCode$1 = 'insufficient_balance' | 'network_error' | 'pre_checkout_rejected' | 'pre_checkout_timeout' | 'unknown';
|
|
44
|
+
/**
|
|
45
|
+
* Payment test scenarios for simulating different payment outcomes.
|
|
46
|
+
*
|
|
47
|
+
* | Scenario | Client sees | Webhook |
|
|
48
|
+
* |----------|-------------|---------|
|
|
49
|
+
* | `'paid'` | `paid` | `{ status: 'finalized' }` |
|
|
50
|
+
* | `'paid:failed'` | `paid` | `{ status: 'failed' }` |
|
|
51
|
+
* | `'cancelled'` | `cancelled` | none |
|
|
52
|
+
* | `'error:*'` | `failed` | none (pre-broadcast) |
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* // Happy path: client paid, tx finalized
|
|
56
|
+
* test: 'paid'
|
|
57
|
+
*
|
|
58
|
+
* // On-chain failure: client paid, tx failed
|
|
59
|
+
* test: 'paid:failed'
|
|
60
|
+
*
|
|
61
|
+
* // User cancelled before confirming
|
|
62
|
+
* test: 'cancelled'
|
|
63
|
+
*
|
|
64
|
+
* // Pre-broadcast error (no tx, no webhook)
|
|
65
|
+
* test: 'error:insufficient_balance'
|
|
66
|
+
*
|
|
67
|
+
* @since 0.1.2
|
|
68
|
+
* @schema
|
|
69
|
+
*/
|
|
70
|
+
type PaymentTestScenario = 'paid' | 'paid:failed' | 'cancelled' | `error:${PaymentErrorCode$1}`;
|
|
36
71
|
//#endregion
|
|
37
72
|
//#region ../contract/src/events/types/payload.d.ts
|
|
38
73
|
/**
|
|
@@ -80,7 +115,7 @@ interface Events {
|
|
|
80
115
|
* Payment status.
|
|
81
116
|
* - `paid`: Success
|
|
82
117
|
* - `cancelled`: User rejected
|
|
83
|
-
* - `failed`:
|
|
118
|
+
* - `failed`: Sending transaction failed (check `errorCode`)
|
|
84
119
|
* @since 0.1.1
|
|
85
120
|
* @schema
|
|
86
121
|
*/
|
|
@@ -101,7 +136,7 @@ interface Events {
|
|
|
101
136
|
* @since 0.1.1
|
|
102
137
|
* @schema
|
|
103
138
|
*/
|
|
104
|
-
errorCode?:
|
|
139
|
+
errorCode?: PaymentErrorCode$1;
|
|
105
140
|
}>>;
|
|
106
141
|
/**
|
|
107
142
|
* Clipboard read response.
|
|
@@ -253,37 +288,62 @@ interface Methods {
|
|
|
253
288
|
*/
|
|
254
289
|
invoice: string;
|
|
255
290
|
/**
|
|
256
|
-
*
|
|
291
|
+
* Optional item details shown on the approval screen.
|
|
257
292
|
* @since 0.1.1
|
|
258
293
|
* @schema
|
|
259
294
|
*/
|
|
260
|
-
|
|
295
|
+
item?: {
|
|
296
|
+
/**
|
|
297
|
+
* Item title shown on the approval screen.
|
|
298
|
+
* @since 0.1.1
|
|
299
|
+
* @schema
|
|
300
|
+
*/
|
|
301
|
+
title: string;
|
|
302
|
+
/**
|
|
303
|
+
* Item icon URL shown on the approval screen.
|
|
304
|
+
* @since 0.1.1
|
|
305
|
+
* @schema
|
|
306
|
+
*/
|
|
307
|
+
iconUrl: string;
|
|
308
|
+
/**
|
|
309
|
+
* Quantity of items being purchased.
|
|
310
|
+
* @since 0.1.1
|
|
311
|
+
* @schema
|
|
312
|
+
*/
|
|
313
|
+
quantity: number;
|
|
314
|
+
};
|
|
261
315
|
/**
|
|
262
|
-
*
|
|
316
|
+
* Test mode. Simulates payment outcomes without real transactions.
|
|
317
|
+
*
|
|
318
|
+
* | Scenario | Client | Webhook |
|
|
319
|
+
* |----------|--------|---------|
|
|
320
|
+
* | `true` / `'paid'` | `paid` | `finalized` |
|
|
321
|
+
* | `'paid:failed'` | `paid` | `failed` |
|
|
322
|
+
* | `'cancelled'` | `cancelled` | none |
|
|
323
|
+
* | `'error:*'` | `failed` | none |
|
|
324
|
+
*
|
|
325
|
+
* **Pre-broadcast errors** (no webhook):
|
|
326
|
+
* `'error:insufficient_balance'`, `'error:network_error'`,
|
|
327
|
+
* `'error:pre_checkout_rejected'`, `'error:pre_checkout_timeout'`,
|
|
328
|
+
* `'error:unknown'`
|
|
329
|
+
*
|
|
330
|
+
* @example
|
|
331
|
+
* // Happy path
|
|
332
|
+
* test: 'paid'
|
|
333
|
+
*
|
|
334
|
+
* // Client shows success, but tx failed on-chain
|
|
335
|
+
* test: 'paid:failed'
|
|
336
|
+
*
|
|
337
|
+
* // User cancelled
|
|
338
|
+
* test: 'cancelled'
|
|
339
|
+
*
|
|
340
|
+
* // Pre-broadcast failure
|
|
341
|
+
* test: 'error:insufficient_balance'
|
|
342
|
+
*
|
|
263
343
|
* @since 0.1.1
|
|
264
344
|
* @schema
|
|
265
345
|
*/
|
|
266
|
-
|
|
267
|
-
/**
|
|
268
|
-
* Item icon URL shown on the approval screen.
|
|
269
|
-
* @since 0.1.1
|
|
270
|
-
* @schema
|
|
271
|
-
*/
|
|
272
|
-
iconUrl?: string;
|
|
273
|
-
/**
|
|
274
|
-
* Quantity of items being purchased.
|
|
275
|
-
* @since 0.1.1
|
|
276
|
-
* @schema
|
|
277
|
-
*/
|
|
278
|
-
quantity?: number;
|
|
279
|
-
/**
|
|
280
|
-
* Test mode flag. When true, no real payment is processed.
|
|
281
|
-
* The approval screen shows a test indicator, and webhooks
|
|
282
|
-
* include `test: true`. Use for development and testing.
|
|
283
|
-
* @since 0.1.1
|
|
284
|
-
* @schema
|
|
285
|
-
*/
|
|
286
|
-
test?: boolean;
|
|
346
|
+
test?: boolean | PaymentTestScenario;
|
|
287
347
|
}>>;
|
|
288
348
|
/**
|
|
289
349
|
* Write text to the system clipboard.
|
|
@@ -304,6 +364,44 @@ interface Methods {
|
|
|
304
364
|
* @schema
|
|
305
365
|
*/
|
|
306
366
|
'clipboard:read': CreateMethodPayload<WithReqId<Empty>>;
|
|
367
|
+
/**
|
|
368
|
+
* Open a URL.
|
|
369
|
+
*
|
|
370
|
+
* The host app acts as middleware: parses the URL, checks permissions/auth,
|
|
371
|
+
* and routes to the appropriate handler based on URL and `openMode`.
|
|
372
|
+
*
|
|
373
|
+
* **`external`** (default) - Open outside the host app:
|
|
374
|
+
* - Custom schemes (`solana:`, `mailto:`) → system handler
|
|
375
|
+
* - HTTPS → system browser
|
|
376
|
+
*
|
|
377
|
+
* **`internal`** - Open within the host app:
|
|
378
|
+
* - Miniapp links → open miniapp (handles auth if required)
|
|
379
|
+
* - Other links → in-app webview
|
|
380
|
+
*
|
|
381
|
+
* @example
|
|
382
|
+
* emit('link:open', { url: 'solana:...' });
|
|
383
|
+
* emit('link:open', { url: 'mailto:hi@example.com' });
|
|
384
|
+
* emit('link:open', { url: 'https://example.com', openMode: 'internal' });
|
|
385
|
+
*
|
|
386
|
+
* @since 0.1.3
|
|
387
|
+
* @schema
|
|
388
|
+
*/
|
|
389
|
+
'link:open': CreateMethodPayload<{
|
|
390
|
+
/**
|
|
391
|
+
* The URL to open.
|
|
392
|
+
* @since 0.1.3
|
|
393
|
+
* @schema
|
|
394
|
+
*/
|
|
395
|
+
url: string;
|
|
396
|
+
/**
|
|
397
|
+
* Where to open the URL.
|
|
398
|
+
* - `external` (default): System browser or app handler
|
|
399
|
+
* - `internal`: Within the host app (miniapps, webviews)
|
|
400
|
+
* @since 0.1.3
|
|
401
|
+
* @schema
|
|
402
|
+
*/
|
|
403
|
+
openMode?: 'external' | 'internal';
|
|
404
|
+
}>;
|
|
307
405
|
}
|
|
308
406
|
//#endregion
|
|
309
407
|
//#region ../contract/src/methods/types/method-types.d.ts
|
|
@@ -479,6 +577,58 @@ declare class MethodNotSupportedError extends ReactSDKError {
|
|
|
479
577
|
*/
|
|
480
578
|
declare function useAlien(): AlienContextValue;
|
|
481
579
|
//#endregion
|
|
580
|
+
//#region src/hooks/useClipboard.d.ts
|
|
581
|
+
/** Clipboard error codes from the host app. */
|
|
582
|
+
type ClipboardErrorCode = 'permission_denied' | 'unavailable';
|
|
583
|
+
interface UseClipboardOptions {
|
|
584
|
+
/**
|
|
585
|
+
* Timeout for clipboard read in milliseconds.
|
|
586
|
+
* @default 5000
|
|
587
|
+
*/
|
|
588
|
+
timeout?: number;
|
|
589
|
+
}
|
|
590
|
+
interface UseClipboardReturn {
|
|
591
|
+
/** Write text to clipboard. Fire-and-forget. */
|
|
592
|
+
writeText: (text: string) => void;
|
|
593
|
+
/** Read text from clipboard. Returns text or null on failure. */
|
|
594
|
+
readText: () => Promise<string | null>;
|
|
595
|
+
/** Whether a read operation is in progress. */
|
|
596
|
+
isReading: boolean;
|
|
597
|
+
/** Error code from the last failed read operation. */
|
|
598
|
+
errorCode: ClipboardErrorCode | null;
|
|
599
|
+
/** Whether clipboard methods are supported by the host app. */
|
|
600
|
+
supported: boolean;
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* Hook for clipboard operations.
|
|
604
|
+
*
|
|
605
|
+
* @example
|
|
606
|
+
* ```tsx
|
|
607
|
+
* function ClipboardDemo() {
|
|
608
|
+
* const { writeText, readText, isReading, errorCode, supported } = useClipboard();
|
|
609
|
+
*
|
|
610
|
+
* if (!supported) return null;
|
|
611
|
+
*
|
|
612
|
+
* return (
|
|
613
|
+
* <>
|
|
614
|
+
* <button onClick={() => writeText('Hello!')}>Copy</button>
|
|
615
|
+
* <button
|
|
616
|
+
* onClick={async () => {
|
|
617
|
+
* const text = await readText();
|
|
618
|
+
* if (text !== null) console.log('Pasted:', text);
|
|
619
|
+
* }}
|
|
620
|
+
* disabled={isReading}
|
|
621
|
+
* >
|
|
622
|
+
* Paste
|
|
623
|
+
* </button>
|
|
624
|
+
* {errorCode && <span>Error: {errorCode}</span>}
|
|
625
|
+
* </>
|
|
626
|
+
* );
|
|
627
|
+
* }
|
|
628
|
+
* ```
|
|
629
|
+
*/
|
|
630
|
+
declare function useClipboard(options?: UseClipboardOptions): UseClipboardReturn;
|
|
631
|
+
//#endregion
|
|
482
632
|
//#region src/hooks/useEvent.d.ts
|
|
483
633
|
type EventCallback<E extends EventName> = (payload: EventPayload<E>) => void;
|
|
484
634
|
/**
|
|
@@ -762,4 +912,4 @@ interface UsePaymentReturn {
|
|
|
762
912
|
*/
|
|
763
913
|
declare function usePayment(options?: UsePaymentOptions): UsePaymentReturn;
|
|
764
914
|
//#endregion
|
|
765
|
-
export { AlienProvider, type AlienProviderProps, BridgeError, BridgeTimeoutError, BridgeUnavailableError, BridgeWindowUnavailableError, type EventName, type EventPayload, type MethodName, MethodNotSupportedError, type MethodPayload, type MethodSupportResult, type PaymentCallbacks, type PaymentErrorCode, type PaymentParams, type PaymentResponseStatus, type PaymentResult, type PaymentStatus, ReactSDKError, type RequestOptions, type UseMethodExecuteResult, type UseMethodOptions, type UsePaymentOptions, type UsePaymentReturn, type Version, getMethodMinVersion, isMethodSupported, send, useAlien, useEvent, useIsMethodSupported, useLaunchParams, useMethod, usePayment };
|
|
915
|
+
export { AlienProvider, type AlienProviderProps, BridgeError, BridgeTimeoutError, BridgeUnavailableError, BridgeWindowUnavailableError, type ClipboardErrorCode, type EventName, type EventPayload, type MethodName, MethodNotSupportedError, type MethodPayload, type MethodSupportResult, type PaymentCallbacks, type PaymentErrorCode, type PaymentParams, type PaymentResponseStatus, type PaymentResult, type PaymentStatus, ReactSDKError, type RequestOptions, type UseClipboardOptions, type UseClipboardReturn, type UseMethodExecuteResult, type UseMethodOptions, type UsePaymentOptions, type UsePaymentReturn, type Version, getMethodMinVersion, isMethodSupported, send, useAlien, useClipboard, useEvent, useIsMethodSupported, useLaunchParams, useMethod, usePayment };
|
package/dist/index.d.mts
CHANGED
|
@@ -33,6 +33,41 @@ type UnionKeys<T> = T extends T ? keyof T : never;
|
|
|
33
33
|
* // Empty = {}
|
|
34
34
|
*/
|
|
35
35
|
type Empty = Record<string, never>;
|
|
36
|
+
/**
|
|
37
|
+
* Client-side payment error codes (pre-broadcast failures).
|
|
38
|
+
* Returned when `status` is `'failed'` in `payment:response`.
|
|
39
|
+
* These errors occur before transaction broadcast, so no webhook is sent.
|
|
40
|
+
* @since 0.1.1
|
|
41
|
+
* @schema
|
|
42
|
+
*/
|
|
43
|
+
type PaymentErrorCode$1 = 'insufficient_balance' | 'network_error' | 'pre_checkout_rejected' | 'pre_checkout_timeout' | 'unknown';
|
|
44
|
+
/**
|
|
45
|
+
* Payment test scenarios for simulating different payment outcomes.
|
|
46
|
+
*
|
|
47
|
+
* | Scenario | Client sees | Webhook |
|
|
48
|
+
* |----------|-------------|---------|
|
|
49
|
+
* | `'paid'` | `paid` | `{ status: 'finalized' }` |
|
|
50
|
+
* | `'paid:failed'` | `paid` | `{ status: 'failed' }` |
|
|
51
|
+
* | `'cancelled'` | `cancelled` | none |
|
|
52
|
+
* | `'error:*'` | `failed` | none (pre-broadcast) |
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* // Happy path: client paid, tx finalized
|
|
56
|
+
* test: 'paid'
|
|
57
|
+
*
|
|
58
|
+
* // On-chain failure: client paid, tx failed
|
|
59
|
+
* test: 'paid:failed'
|
|
60
|
+
*
|
|
61
|
+
* // User cancelled before confirming
|
|
62
|
+
* test: 'cancelled'
|
|
63
|
+
*
|
|
64
|
+
* // Pre-broadcast error (no tx, no webhook)
|
|
65
|
+
* test: 'error:insufficient_balance'
|
|
66
|
+
*
|
|
67
|
+
* @since 0.1.2
|
|
68
|
+
* @schema
|
|
69
|
+
*/
|
|
70
|
+
type PaymentTestScenario = 'paid' | 'paid:failed' | 'cancelled' | `error:${PaymentErrorCode$1}`;
|
|
36
71
|
//#endregion
|
|
37
72
|
//#region ../contract/src/events/types/payload.d.ts
|
|
38
73
|
/**
|
|
@@ -80,7 +115,7 @@ interface Events {
|
|
|
80
115
|
* Payment status.
|
|
81
116
|
* - `paid`: Success
|
|
82
117
|
* - `cancelled`: User rejected
|
|
83
|
-
* - `failed`:
|
|
118
|
+
* - `failed`: Sending transaction failed (check `errorCode`)
|
|
84
119
|
* @since 0.1.1
|
|
85
120
|
* @schema
|
|
86
121
|
*/
|
|
@@ -101,7 +136,7 @@ interface Events {
|
|
|
101
136
|
* @since 0.1.1
|
|
102
137
|
* @schema
|
|
103
138
|
*/
|
|
104
|
-
errorCode?:
|
|
139
|
+
errorCode?: PaymentErrorCode$1;
|
|
105
140
|
}>>;
|
|
106
141
|
/**
|
|
107
142
|
* Clipboard read response.
|
|
@@ -253,37 +288,62 @@ interface Methods {
|
|
|
253
288
|
*/
|
|
254
289
|
invoice: string;
|
|
255
290
|
/**
|
|
256
|
-
*
|
|
291
|
+
* Optional item details shown on the approval screen.
|
|
257
292
|
* @since 0.1.1
|
|
258
293
|
* @schema
|
|
259
294
|
*/
|
|
260
|
-
|
|
295
|
+
item?: {
|
|
296
|
+
/**
|
|
297
|
+
* Item title shown on the approval screen.
|
|
298
|
+
* @since 0.1.1
|
|
299
|
+
* @schema
|
|
300
|
+
*/
|
|
301
|
+
title: string;
|
|
302
|
+
/**
|
|
303
|
+
* Item icon URL shown on the approval screen.
|
|
304
|
+
* @since 0.1.1
|
|
305
|
+
* @schema
|
|
306
|
+
*/
|
|
307
|
+
iconUrl: string;
|
|
308
|
+
/**
|
|
309
|
+
* Quantity of items being purchased.
|
|
310
|
+
* @since 0.1.1
|
|
311
|
+
* @schema
|
|
312
|
+
*/
|
|
313
|
+
quantity: number;
|
|
314
|
+
};
|
|
261
315
|
/**
|
|
262
|
-
*
|
|
316
|
+
* Test mode. Simulates payment outcomes without real transactions.
|
|
317
|
+
*
|
|
318
|
+
* | Scenario | Client | Webhook |
|
|
319
|
+
* |----------|--------|---------|
|
|
320
|
+
* | `true` / `'paid'` | `paid` | `finalized` |
|
|
321
|
+
* | `'paid:failed'` | `paid` | `failed` |
|
|
322
|
+
* | `'cancelled'` | `cancelled` | none |
|
|
323
|
+
* | `'error:*'` | `failed` | none |
|
|
324
|
+
*
|
|
325
|
+
* **Pre-broadcast errors** (no webhook):
|
|
326
|
+
* `'error:insufficient_balance'`, `'error:network_error'`,
|
|
327
|
+
* `'error:pre_checkout_rejected'`, `'error:pre_checkout_timeout'`,
|
|
328
|
+
* `'error:unknown'`
|
|
329
|
+
*
|
|
330
|
+
* @example
|
|
331
|
+
* // Happy path
|
|
332
|
+
* test: 'paid'
|
|
333
|
+
*
|
|
334
|
+
* // Client shows success, but tx failed on-chain
|
|
335
|
+
* test: 'paid:failed'
|
|
336
|
+
*
|
|
337
|
+
* // User cancelled
|
|
338
|
+
* test: 'cancelled'
|
|
339
|
+
*
|
|
340
|
+
* // Pre-broadcast failure
|
|
341
|
+
* test: 'error:insufficient_balance'
|
|
342
|
+
*
|
|
263
343
|
* @since 0.1.1
|
|
264
344
|
* @schema
|
|
265
345
|
*/
|
|
266
|
-
|
|
267
|
-
/**
|
|
268
|
-
* Item icon URL shown on the approval screen.
|
|
269
|
-
* @since 0.1.1
|
|
270
|
-
* @schema
|
|
271
|
-
*/
|
|
272
|
-
iconUrl?: string;
|
|
273
|
-
/**
|
|
274
|
-
* Quantity of items being purchased.
|
|
275
|
-
* @since 0.1.1
|
|
276
|
-
* @schema
|
|
277
|
-
*/
|
|
278
|
-
quantity?: number;
|
|
279
|
-
/**
|
|
280
|
-
* Test mode flag. When true, no real payment is processed.
|
|
281
|
-
* The approval screen shows a test indicator, and webhooks
|
|
282
|
-
* include `test: true`. Use for development and testing.
|
|
283
|
-
* @since 0.1.1
|
|
284
|
-
* @schema
|
|
285
|
-
*/
|
|
286
|
-
test?: boolean;
|
|
346
|
+
test?: boolean | PaymentTestScenario;
|
|
287
347
|
}>>;
|
|
288
348
|
/**
|
|
289
349
|
* Write text to the system clipboard.
|
|
@@ -304,6 +364,44 @@ interface Methods {
|
|
|
304
364
|
* @schema
|
|
305
365
|
*/
|
|
306
366
|
'clipboard:read': CreateMethodPayload<WithReqId<Empty>>;
|
|
367
|
+
/**
|
|
368
|
+
* Open a URL.
|
|
369
|
+
*
|
|
370
|
+
* The host app acts as middleware: parses the URL, checks permissions/auth,
|
|
371
|
+
* and routes to the appropriate handler based on URL and `openMode`.
|
|
372
|
+
*
|
|
373
|
+
* **`external`** (default) - Open outside the host app:
|
|
374
|
+
* - Custom schemes (`solana:`, `mailto:`) → system handler
|
|
375
|
+
* - HTTPS → system browser
|
|
376
|
+
*
|
|
377
|
+
* **`internal`** - Open within the host app:
|
|
378
|
+
* - Miniapp links → open miniapp (handles auth if required)
|
|
379
|
+
* - Other links → in-app webview
|
|
380
|
+
*
|
|
381
|
+
* @example
|
|
382
|
+
* emit('link:open', { url: 'solana:...' });
|
|
383
|
+
* emit('link:open', { url: 'mailto:hi@example.com' });
|
|
384
|
+
* emit('link:open', { url: 'https://example.com', openMode: 'internal' });
|
|
385
|
+
*
|
|
386
|
+
* @since 0.1.3
|
|
387
|
+
* @schema
|
|
388
|
+
*/
|
|
389
|
+
'link:open': CreateMethodPayload<{
|
|
390
|
+
/**
|
|
391
|
+
* The URL to open.
|
|
392
|
+
* @since 0.1.3
|
|
393
|
+
* @schema
|
|
394
|
+
*/
|
|
395
|
+
url: string;
|
|
396
|
+
/**
|
|
397
|
+
* Where to open the URL.
|
|
398
|
+
* - `external` (default): System browser or app handler
|
|
399
|
+
* - `internal`: Within the host app (miniapps, webviews)
|
|
400
|
+
* @since 0.1.3
|
|
401
|
+
* @schema
|
|
402
|
+
*/
|
|
403
|
+
openMode?: 'external' | 'internal';
|
|
404
|
+
}>;
|
|
307
405
|
}
|
|
308
406
|
//#endregion
|
|
309
407
|
//#region ../contract/src/methods/types/method-types.d.ts
|
|
@@ -479,6 +577,58 @@ declare class MethodNotSupportedError extends ReactSDKError {
|
|
|
479
577
|
*/
|
|
480
578
|
declare function useAlien(): AlienContextValue;
|
|
481
579
|
//#endregion
|
|
580
|
+
//#region src/hooks/useClipboard.d.ts
|
|
581
|
+
/** Clipboard error codes from the host app. */
|
|
582
|
+
type ClipboardErrorCode = 'permission_denied' | 'unavailable';
|
|
583
|
+
interface UseClipboardOptions {
|
|
584
|
+
/**
|
|
585
|
+
* Timeout for clipboard read in milliseconds.
|
|
586
|
+
* @default 5000
|
|
587
|
+
*/
|
|
588
|
+
timeout?: number;
|
|
589
|
+
}
|
|
590
|
+
interface UseClipboardReturn {
|
|
591
|
+
/** Write text to clipboard. Fire-and-forget. */
|
|
592
|
+
writeText: (text: string) => void;
|
|
593
|
+
/** Read text from clipboard. Returns text or null on failure. */
|
|
594
|
+
readText: () => Promise<string | null>;
|
|
595
|
+
/** Whether a read operation is in progress. */
|
|
596
|
+
isReading: boolean;
|
|
597
|
+
/** Error code from the last failed read operation. */
|
|
598
|
+
errorCode: ClipboardErrorCode | null;
|
|
599
|
+
/** Whether clipboard methods are supported by the host app. */
|
|
600
|
+
supported: boolean;
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* Hook for clipboard operations.
|
|
604
|
+
*
|
|
605
|
+
* @example
|
|
606
|
+
* ```tsx
|
|
607
|
+
* function ClipboardDemo() {
|
|
608
|
+
* const { writeText, readText, isReading, errorCode, supported } = useClipboard();
|
|
609
|
+
*
|
|
610
|
+
* if (!supported) return null;
|
|
611
|
+
*
|
|
612
|
+
* return (
|
|
613
|
+
* <>
|
|
614
|
+
* <button onClick={() => writeText('Hello!')}>Copy</button>
|
|
615
|
+
* <button
|
|
616
|
+
* onClick={async () => {
|
|
617
|
+
* const text = await readText();
|
|
618
|
+
* if (text !== null) console.log('Pasted:', text);
|
|
619
|
+
* }}
|
|
620
|
+
* disabled={isReading}
|
|
621
|
+
* >
|
|
622
|
+
* Paste
|
|
623
|
+
* </button>
|
|
624
|
+
* {errorCode && <span>Error: {errorCode}</span>}
|
|
625
|
+
* </>
|
|
626
|
+
* );
|
|
627
|
+
* }
|
|
628
|
+
* ```
|
|
629
|
+
*/
|
|
630
|
+
declare function useClipboard(options?: UseClipboardOptions): UseClipboardReturn;
|
|
631
|
+
//#endregion
|
|
482
632
|
//#region src/hooks/useEvent.d.ts
|
|
483
633
|
type EventCallback<E extends EventName> = (payload: EventPayload<E>) => void;
|
|
484
634
|
/**
|
|
@@ -762,4 +912,4 @@ interface UsePaymentReturn {
|
|
|
762
912
|
*/
|
|
763
913
|
declare function usePayment(options?: UsePaymentOptions): UsePaymentReturn;
|
|
764
914
|
//#endregion
|
|
765
|
-
export { AlienProvider, type AlienProviderProps, BridgeError, BridgeTimeoutError, BridgeUnavailableError, BridgeWindowUnavailableError, type EventName, type EventPayload, type MethodName, MethodNotSupportedError, type MethodPayload, type MethodSupportResult, type PaymentCallbacks, type PaymentErrorCode, type PaymentParams, type PaymentResponseStatus, type PaymentResult, type PaymentStatus, ReactSDKError, type RequestOptions, type UseMethodExecuteResult, type UseMethodOptions, type UsePaymentOptions, type UsePaymentReturn, type Version, getMethodMinVersion, isMethodSupported, send, useAlien, useEvent, useIsMethodSupported, useLaunchParams, useMethod, usePayment };
|
|
915
|
+
export { AlienProvider, type AlienProviderProps, BridgeError, BridgeTimeoutError, BridgeUnavailableError, BridgeWindowUnavailableError, type ClipboardErrorCode, type EventName, type EventPayload, type MethodName, MethodNotSupportedError, type MethodPayload, type MethodSupportResult, type PaymentCallbacks, type PaymentErrorCode, type PaymentParams, type PaymentResponseStatus, type PaymentResult, type PaymentStatus, ReactSDKError, type RequestOptions, type UseClipboardOptions, type UseClipboardReturn, type UseMethodExecuteResult, type UseMethodOptions, type UsePaymentOptions, type UsePaymentReturn, type Version, getMethodMinVersion, isMethodSupported, send, useAlien, useClipboard, useEvent, useIsMethodSupported, useLaunchParams, useMethod, usePayment };
|
package/dist/index.mjs
CHANGED
|
@@ -91,6 +91,84 @@ function useAlien() {
|
|
|
91
91
|
return context;
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
//#endregion
|
|
95
|
+
//#region src/hooks/useClipboard.ts
|
|
96
|
+
/**
|
|
97
|
+
* Hook for clipboard operations.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```tsx
|
|
101
|
+
* function ClipboardDemo() {
|
|
102
|
+
* const { writeText, readText, isReading, errorCode, supported } = useClipboard();
|
|
103
|
+
*
|
|
104
|
+
* if (!supported) return null;
|
|
105
|
+
*
|
|
106
|
+
* return (
|
|
107
|
+
* <>
|
|
108
|
+
* <button onClick={() => writeText('Hello!')}>Copy</button>
|
|
109
|
+
* <button
|
|
110
|
+
* onClick={async () => {
|
|
111
|
+
* const text = await readText();
|
|
112
|
+
* if (text !== null) console.log('Pasted:', text);
|
|
113
|
+
* }}
|
|
114
|
+
* disabled={isReading}
|
|
115
|
+
* >
|
|
116
|
+
* Paste
|
|
117
|
+
* </button>
|
|
118
|
+
* {errorCode && <span>Error: {errorCode}</span>}
|
|
119
|
+
* </>
|
|
120
|
+
* );
|
|
121
|
+
* }
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
124
|
+
function useClipboard(options = {}) {
|
|
125
|
+
const { timeout = 5e3 } = options;
|
|
126
|
+
const { contractVersion, isBridgeAvailable: isBridgeAvailable$1 } = useAlien();
|
|
127
|
+
const [isReading, setIsReading] = useState(false);
|
|
128
|
+
const [errorCode, setErrorCode] = useState(null);
|
|
129
|
+
const supported = contractVersion ? isMethodSupported$1("clipboard:write", contractVersion) && isMethodSupported$1("clipboard:read", contractVersion) : true;
|
|
130
|
+
const writeText = useCallback((text) => {
|
|
131
|
+
if (!isBridgeAvailable$1) return;
|
|
132
|
+
if (contractVersion && !isMethodSupported$1("clipboard:write", contractVersion)) return;
|
|
133
|
+
send$1("clipboard:write", { text });
|
|
134
|
+
}, [isBridgeAvailable$1, contractVersion]);
|
|
135
|
+
const readText = useCallback(async () => {
|
|
136
|
+
if (!isBridgeAvailable$1) return null;
|
|
137
|
+
if (contractVersion && !isMethodSupported$1("clipboard:read", contractVersion)) return null;
|
|
138
|
+
setIsReading(true);
|
|
139
|
+
setErrorCode(null);
|
|
140
|
+
try {
|
|
141
|
+
const response = await request("clipboard:read", {}, "clipboard:response", { timeout });
|
|
142
|
+
if (response.errorCode) {
|
|
143
|
+
setErrorCode(response.errorCode);
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
return response.text;
|
|
147
|
+
} catch {
|
|
148
|
+
return null;
|
|
149
|
+
} finally {
|
|
150
|
+
setIsReading(false);
|
|
151
|
+
}
|
|
152
|
+
}, [
|
|
153
|
+
isBridgeAvailable$1,
|
|
154
|
+
contractVersion,
|
|
155
|
+
timeout
|
|
156
|
+
]);
|
|
157
|
+
return useMemo(() => ({
|
|
158
|
+
writeText,
|
|
159
|
+
readText,
|
|
160
|
+
isReading,
|
|
161
|
+
errorCode,
|
|
162
|
+
supported
|
|
163
|
+
}), [
|
|
164
|
+
writeText,
|
|
165
|
+
readText,
|
|
166
|
+
isReading,
|
|
167
|
+
errorCode,
|
|
168
|
+
supported
|
|
169
|
+
]);
|
|
170
|
+
}
|
|
171
|
+
|
|
94
172
|
//#endregion
|
|
95
173
|
//#region src/hooks/useEvent.ts
|
|
96
174
|
/**
|
|
@@ -513,4 +591,4 @@ function usePayment(options = {}) {
|
|
|
513
591
|
}
|
|
514
592
|
|
|
515
593
|
//#endregion
|
|
516
|
-
export { AlienProvider, BridgeError, BridgeTimeoutError, BridgeUnavailableError, BridgeWindowUnavailableError, MethodNotSupportedError, ReactSDKError, getMethodMinVersion, isMethodSupported, send, useAlien, useEvent, useIsMethodSupported, useLaunchParams, useMethod, usePayment };
|
|
594
|
+
export { AlienProvider, BridgeError, BridgeTimeoutError, BridgeUnavailableError, BridgeWindowUnavailableError, MethodNotSupportedError, ReactSDKError, getMethodMinVersion, isMethodSupported, send, useAlien, useClipboard, useEvent, useIsMethodSupported, useLaunchParams, useMethod, usePayment };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alien_org/react",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"prepublishOnly": "bun run build"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@alien_org/bridge": "0.1.
|
|
38
|
-
"@alien_org/contract": "0.1.
|
|
37
|
+
"@alien_org/bridge": "0.1.2",
|
|
38
|
+
"@alien_org/contract": "0.1.4"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"react": "^18 || ^19",
|