@fragmentpay/react 0.3.4 → 0.4.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.d.mts +47 -3
- package/dist/index.d.ts +47 -3
- package/dist/index.js +62 -1
- package/dist/index.mjs +60 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -8,7 +8,7 @@ import * as React from 'react';
|
|
|
8
8
|
|
|
9
9
|
interface FragmentPayProviderProps {
|
|
10
10
|
publicKey: string;
|
|
11
|
-
/** Override the API/host origin. Defaults to https://frag.
|
|
11
|
+
/** Override the API/host origin. Defaults to https://frag.cash. */
|
|
12
12
|
baseUrl?: string;
|
|
13
13
|
children: React.ReactNode;
|
|
14
14
|
}
|
|
@@ -25,14 +25,43 @@ interface FetchWithRetryOpts extends RequestInit {
|
|
|
25
25
|
* with jitter for retryable failures. Exposed for advanced integrators.
|
|
26
26
|
*/
|
|
27
27
|
declare function fetchWithRetry(input: string, init?: FetchWithRetryOpts): Promise<Response>;
|
|
28
|
-
type IntentStatus = "created" | "requires_payment" | "quoted" | "executing" | "settled" | "failed" | "expired" | "cancelled" | "refunded";
|
|
28
|
+
type IntentStatus = "created" | "requires_payment" | "quoted" | "awaiting_signature" | "executing" | "partially_filled" | "settled" | "failed" | "expired" | "cancelled" | "refunded";
|
|
29
29
|
interface PublicIntent {
|
|
30
30
|
id: string;
|
|
31
31
|
amount: string;
|
|
32
32
|
currency: string;
|
|
33
33
|
status: IntentStatus;
|
|
34
|
+
settlement_chain?: string | null;
|
|
35
|
+
settlement_token?: string | null;
|
|
36
|
+
expires_at?: string;
|
|
34
37
|
metadata?: Record<string, unknown>;
|
|
35
38
|
}
|
|
39
|
+
type RefundStatus = "pending" | "processing" | "retry_scheduled" | "succeeded" | "failed";
|
|
40
|
+
type RefundPhase = "queued" | "sent" | "completed" | "failed";
|
|
41
|
+
/**
|
|
42
|
+
* Bucket a raw refund status into a stable UI phase. Mirrors the identical
|
|
43
|
+
* helper in `@fragmentpay/server` so front-end and back-end render matching
|
|
44
|
+
* status pills.
|
|
45
|
+
*/
|
|
46
|
+
declare function refundPhase(status: RefundStatus | string | null | undefined): RefundPhase;
|
|
47
|
+
interface PublicRefundStatus {
|
|
48
|
+
id: string;
|
|
49
|
+
payment_intent_id: string;
|
|
50
|
+
amount_usd: number;
|
|
51
|
+
chain: string | null;
|
|
52
|
+
token: string | null;
|
|
53
|
+
destination_tail: string;
|
|
54
|
+
reason: string;
|
|
55
|
+
status: RefundStatus;
|
|
56
|
+
phase: RefundPhase;
|
|
57
|
+
tx_hash: string | null;
|
|
58
|
+
failure_reason: string | null;
|
|
59
|
+
attempts: number;
|
|
60
|
+
created_at: string;
|
|
61
|
+
updated_at: string;
|
|
62
|
+
paid_at: string | null;
|
|
63
|
+
terminal: boolean;
|
|
64
|
+
}
|
|
36
65
|
declare function useFragmentIntent(intentId: string | null, opts?: {
|
|
37
66
|
intervalMs?: number;
|
|
38
67
|
}): {
|
|
@@ -40,6 +69,21 @@ declare function useFragmentIntent(intentId: string | null, opts?: {
|
|
|
40
69
|
status: "idle" | "loading" | "ready" | "error";
|
|
41
70
|
error: string | null;
|
|
42
71
|
};
|
|
72
|
+
/**
|
|
73
|
+
* Poll the payer-facing refund status endpoint at `/api/public/refunds/:id/status`.
|
|
74
|
+
* UNAUTHENTICATED — safe to use in customer-facing receipt / order-tracking UIs.
|
|
75
|
+
*
|
|
76
|
+
* Returns `{ data, status, error }` where `data.phase` buckets the raw refund
|
|
77
|
+
* state into `queued | sent | completed | failed` for a stable status pill.
|
|
78
|
+
* Polling stops automatically once `data.terminal === true`.
|
|
79
|
+
*/
|
|
80
|
+
declare function useFragmentRefund(refundId: string | null, opts?: {
|
|
81
|
+
intervalMs?: number;
|
|
82
|
+
}): {
|
|
83
|
+
data: PublicRefundStatus | null;
|
|
84
|
+
status: "idle" | "loading" | "ready" | "error";
|
|
85
|
+
error: string | null;
|
|
86
|
+
};
|
|
43
87
|
interface FragmentPayCheckoutProps {
|
|
44
88
|
intentId: string;
|
|
45
89
|
/** Called once the intent transitions to `settled`. */
|
|
@@ -96,4 +140,4 @@ interface FragmentPayButtonProps extends UseCreateIntentOptions {
|
|
|
96
140
|
}
|
|
97
141
|
declare function FragmentPayButton({ input, label, onSettled, onError, className, style, ...opts }: FragmentPayButtonProps): React.JSX.Element;
|
|
98
142
|
|
|
99
|
-
export { type FetchWithRetryOpts, type FragToken, FragmentPayButton, type FragmentPayButtonProps, FragmentPayCheckout, type FragmentPayCheckoutProps, FragmentPayProvider, type FragmentPayProviderProps, type IntentStatus, type PublicIntent, type UseCreateIntentOptions, fetchWithRetry, useCreateIntent, useFragmentIntent, useFragmentTokens };
|
|
143
|
+
export { type FetchWithRetryOpts, type FragToken, FragmentPayButton, type FragmentPayButtonProps, FragmentPayCheckout, type FragmentPayCheckoutProps, FragmentPayProvider, type FragmentPayProviderProps, type IntentStatus, type PublicIntent, type PublicRefundStatus, type RefundPhase, type RefundStatus, type UseCreateIntentOptions, fetchWithRetry, refundPhase, useCreateIntent, useFragmentIntent, useFragmentRefund, useFragmentTokens };
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ import * as React from 'react';
|
|
|
8
8
|
|
|
9
9
|
interface FragmentPayProviderProps {
|
|
10
10
|
publicKey: string;
|
|
11
|
-
/** Override the API/host origin. Defaults to https://frag.
|
|
11
|
+
/** Override the API/host origin. Defaults to https://frag.cash. */
|
|
12
12
|
baseUrl?: string;
|
|
13
13
|
children: React.ReactNode;
|
|
14
14
|
}
|
|
@@ -25,14 +25,43 @@ interface FetchWithRetryOpts extends RequestInit {
|
|
|
25
25
|
* with jitter for retryable failures. Exposed for advanced integrators.
|
|
26
26
|
*/
|
|
27
27
|
declare function fetchWithRetry(input: string, init?: FetchWithRetryOpts): Promise<Response>;
|
|
28
|
-
type IntentStatus = "created" | "requires_payment" | "quoted" | "executing" | "settled" | "failed" | "expired" | "cancelled" | "refunded";
|
|
28
|
+
type IntentStatus = "created" | "requires_payment" | "quoted" | "awaiting_signature" | "executing" | "partially_filled" | "settled" | "failed" | "expired" | "cancelled" | "refunded";
|
|
29
29
|
interface PublicIntent {
|
|
30
30
|
id: string;
|
|
31
31
|
amount: string;
|
|
32
32
|
currency: string;
|
|
33
33
|
status: IntentStatus;
|
|
34
|
+
settlement_chain?: string | null;
|
|
35
|
+
settlement_token?: string | null;
|
|
36
|
+
expires_at?: string;
|
|
34
37
|
metadata?: Record<string, unknown>;
|
|
35
38
|
}
|
|
39
|
+
type RefundStatus = "pending" | "processing" | "retry_scheduled" | "succeeded" | "failed";
|
|
40
|
+
type RefundPhase = "queued" | "sent" | "completed" | "failed";
|
|
41
|
+
/**
|
|
42
|
+
* Bucket a raw refund status into a stable UI phase. Mirrors the identical
|
|
43
|
+
* helper in `@fragmentpay/server` so front-end and back-end render matching
|
|
44
|
+
* status pills.
|
|
45
|
+
*/
|
|
46
|
+
declare function refundPhase(status: RefundStatus | string | null | undefined): RefundPhase;
|
|
47
|
+
interface PublicRefundStatus {
|
|
48
|
+
id: string;
|
|
49
|
+
payment_intent_id: string;
|
|
50
|
+
amount_usd: number;
|
|
51
|
+
chain: string | null;
|
|
52
|
+
token: string | null;
|
|
53
|
+
destination_tail: string;
|
|
54
|
+
reason: string;
|
|
55
|
+
status: RefundStatus;
|
|
56
|
+
phase: RefundPhase;
|
|
57
|
+
tx_hash: string | null;
|
|
58
|
+
failure_reason: string | null;
|
|
59
|
+
attempts: number;
|
|
60
|
+
created_at: string;
|
|
61
|
+
updated_at: string;
|
|
62
|
+
paid_at: string | null;
|
|
63
|
+
terminal: boolean;
|
|
64
|
+
}
|
|
36
65
|
declare function useFragmentIntent(intentId: string | null, opts?: {
|
|
37
66
|
intervalMs?: number;
|
|
38
67
|
}): {
|
|
@@ -40,6 +69,21 @@ declare function useFragmentIntent(intentId: string | null, opts?: {
|
|
|
40
69
|
status: "idle" | "loading" | "ready" | "error";
|
|
41
70
|
error: string | null;
|
|
42
71
|
};
|
|
72
|
+
/**
|
|
73
|
+
* Poll the payer-facing refund status endpoint at `/api/public/refunds/:id/status`.
|
|
74
|
+
* UNAUTHENTICATED — safe to use in customer-facing receipt / order-tracking UIs.
|
|
75
|
+
*
|
|
76
|
+
* Returns `{ data, status, error }` where `data.phase` buckets the raw refund
|
|
77
|
+
* state into `queued | sent | completed | failed` for a stable status pill.
|
|
78
|
+
* Polling stops automatically once `data.terminal === true`.
|
|
79
|
+
*/
|
|
80
|
+
declare function useFragmentRefund(refundId: string | null, opts?: {
|
|
81
|
+
intervalMs?: number;
|
|
82
|
+
}): {
|
|
83
|
+
data: PublicRefundStatus | null;
|
|
84
|
+
status: "idle" | "loading" | "ready" | "error";
|
|
85
|
+
error: string | null;
|
|
86
|
+
};
|
|
43
87
|
interface FragmentPayCheckoutProps {
|
|
44
88
|
intentId: string;
|
|
45
89
|
/** Called once the intent transitions to `settled`. */
|
|
@@ -96,4 +140,4 @@ interface FragmentPayButtonProps extends UseCreateIntentOptions {
|
|
|
96
140
|
}
|
|
97
141
|
declare function FragmentPayButton({ input, label, onSettled, onError, className, style, ...opts }: FragmentPayButtonProps): React.JSX.Element;
|
|
98
142
|
|
|
99
|
-
export { type FetchWithRetryOpts, type FragToken, FragmentPayButton, type FragmentPayButtonProps, FragmentPayCheckout, type FragmentPayCheckoutProps, FragmentPayProvider, type FragmentPayProviderProps, type IntentStatus, type PublicIntent, type UseCreateIntentOptions, fetchWithRetry, useCreateIntent, useFragmentIntent, useFragmentTokens };
|
|
143
|
+
export { type FetchWithRetryOpts, type FragToken, FragmentPayButton, type FragmentPayButtonProps, FragmentPayCheckout, type FragmentPayCheckoutProps, FragmentPayProvider, type FragmentPayProviderProps, type IntentStatus, type PublicIntent, type PublicRefundStatus, type RefundPhase, type RefundStatus, type UseCreateIntentOptions, fetchWithRetry, refundPhase, useCreateIntent, useFragmentIntent, useFragmentRefund, useFragmentTokens };
|
package/dist/index.js
CHANGED
|
@@ -34,8 +34,10 @@ __export(index_exports, {
|
|
|
34
34
|
FragmentPayCheckout: () => FragmentPayCheckout,
|
|
35
35
|
FragmentPayProvider: () => FragmentPayProvider,
|
|
36
36
|
fetchWithRetry: () => fetchWithRetry,
|
|
37
|
+
refundPhase: () => refundPhase,
|
|
37
38
|
useCreateIntent: () => useCreateIntent,
|
|
38
39
|
useFragmentIntent: () => useFragmentIntent,
|
|
40
|
+
useFragmentRefund: () => useFragmentRefund,
|
|
39
41
|
useFragmentTokens: () => useFragmentTokens
|
|
40
42
|
});
|
|
41
43
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -56,7 +58,7 @@ function FragmentPayProvider({ publicKey, baseUrl, children }) {
|
|
|
56
58
|
}
|
|
57
59
|
}
|
|
58
60
|
const value = React.useMemo(
|
|
59
|
-
() => ({ publicKey, baseUrl: (baseUrl ?? "https://frag.
|
|
61
|
+
() => ({ publicKey, baseUrl: (baseUrl ?? "https://frag.cash").replace(/\/$/, "") }),
|
|
60
62
|
[publicKey, baseUrl]
|
|
61
63
|
);
|
|
62
64
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FragContext.Provider, { value, children });
|
|
@@ -119,6 +121,18 @@ async function fetchWithRetry(input, init = {}) {
|
|
|
119
121
|
attempt += 1;
|
|
120
122
|
}
|
|
121
123
|
}
|
|
124
|
+
function refundPhase(status) {
|
|
125
|
+
switch (status) {
|
|
126
|
+
case "succeeded":
|
|
127
|
+
return "completed";
|
|
128
|
+
case "processing":
|
|
129
|
+
return "sent";
|
|
130
|
+
case "failed":
|
|
131
|
+
return "failed";
|
|
132
|
+
default:
|
|
133
|
+
return "queued";
|
|
134
|
+
}
|
|
135
|
+
}
|
|
122
136
|
function useFragmentIntent(intentId, opts = {}) {
|
|
123
137
|
const { baseUrl } = useFrag();
|
|
124
138
|
if (intentId !== null && (typeof intentId !== "string" || intentId.length < 3)) {
|
|
@@ -165,6 +179,51 @@ function useFragmentIntent(intentId, opts = {}) {
|
|
|
165
179
|
}, [intentId, baseUrl, interval]);
|
|
166
180
|
return state;
|
|
167
181
|
}
|
|
182
|
+
function useFragmentRefund(refundId, opts = {}) {
|
|
183
|
+
const { baseUrl } = useFrag();
|
|
184
|
+
if (refundId !== null && (typeof refundId !== "string" || refundId.length < 3)) {
|
|
185
|
+
throw new Error("[fragmentpay] useFragmentRefund: refundId must be a non-empty string or null");
|
|
186
|
+
}
|
|
187
|
+
const interval = opts.intervalMs ?? 3e3;
|
|
188
|
+
if (typeof interval !== "number" || interval < 500 || interval > 6e4) {
|
|
189
|
+
throw new Error("[fragmentpay] useFragmentRefund: intervalMs must be between 500 and 60000");
|
|
190
|
+
}
|
|
191
|
+
const [state, setState] = React.useState({ data: null, status: "idle", error: null });
|
|
192
|
+
React.useEffect(() => {
|
|
193
|
+
if (!refundId) return;
|
|
194
|
+
let alive = true;
|
|
195
|
+
let timer;
|
|
196
|
+
async function tick() {
|
|
197
|
+
try {
|
|
198
|
+
const res = await fetchWithRetry(
|
|
199
|
+
`${baseUrl}/api/public/refunds/${refundId}/status`,
|
|
200
|
+
{ maxRetries: 4 }
|
|
201
|
+
);
|
|
202
|
+
if (!res.ok) {
|
|
203
|
+
const retryAfter = parseRetryAfter(res.headers.get("retry-after")) ?? interval * 2;
|
|
204
|
+
throw Object.assign(new Error(`HTTP ${res.status}`), { retryAfter });
|
|
205
|
+
}
|
|
206
|
+
const raw = await res.json();
|
|
207
|
+
const data = { ...raw, phase: refundPhase(raw.status) };
|
|
208
|
+
if (!alive) return;
|
|
209
|
+
setState({ data, status: "ready", error: null });
|
|
210
|
+
if (!data.terminal) timer = setTimeout(tick, interval);
|
|
211
|
+
} catch (e) {
|
|
212
|
+
if (!alive) return;
|
|
213
|
+
const wait = e.retryAfter ?? interval * 2;
|
|
214
|
+
setState((s) => ({ ...s, status: "error", error: e.message }));
|
|
215
|
+
timer = setTimeout(tick, wait);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
setState({ data: null, status: "loading", error: null });
|
|
219
|
+
tick();
|
|
220
|
+
return () => {
|
|
221
|
+
alive = false;
|
|
222
|
+
clearTimeout(timer);
|
|
223
|
+
};
|
|
224
|
+
}, [refundId, baseUrl, interval]);
|
|
225
|
+
return state;
|
|
226
|
+
}
|
|
168
227
|
function FragmentPayCheckout({
|
|
169
228
|
intentId,
|
|
170
229
|
onSettled,
|
|
@@ -299,7 +358,9 @@ function FragmentPayButton({
|
|
|
299
358
|
FragmentPayCheckout,
|
|
300
359
|
FragmentPayProvider,
|
|
301
360
|
fetchWithRetry,
|
|
361
|
+
refundPhase,
|
|
302
362
|
useCreateIntent,
|
|
303
363
|
useFragmentIntent,
|
|
364
|
+
useFragmentRefund,
|
|
304
365
|
useFragmentTokens
|
|
305
366
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -16,7 +16,7 @@ function FragmentPayProvider({ publicKey, baseUrl, children }) {
|
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
const value = React.useMemo(
|
|
19
|
-
() => ({ publicKey, baseUrl: (baseUrl ?? "https://frag.
|
|
19
|
+
() => ({ publicKey, baseUrl: (baseUrl ?? "https://frag.cash").replace(/\/$/, "") }),
|
|
20
20
|
[publicKey, baseUrl]
|
|
21
21
|
);
|
|
22
22
|
return /* @__PURE__ */ jsx(FragContext.Provider, { value, children });
|
|
@@ -79,6 +79,18 @@ async function fetchWithRetry(input, init = {}) {
|
|
|
79
79
|
attempt += 1;
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
|
+
function refundPhase(status) {
|
|
83
|
+
switch (status) {
|
|
84
|
+
case "succeeded":
|
|
85
|
+
return "completed";
|
|
86
|
+
case "processing":
|
|
87
|
+
return "sent";
|
|
88
|
+
case "failed":
|
|
89
|
+
return "failed";
|
|
90
|
+
default:
|
|
91
|
+
return "queued";
|
|
92
|
+
}
|
|
93
|
+
}
|
|
82
94
|
function useFragmentIntent(intentId, opts = {}) {
|
|
83
95
|
const { baseUrl } = useFrag();
|
|
84
96
|
if (intentId !== null && (typeof intentId !== "string" || intentId.length < 3)) {
|
|
@@ -125,6 +137,51 @@ function useFragmentIntent(intentId, opts = {}) {
|
|
|
125
137
|
}, [intentId, baseUrl, interval]);
|
|
126
138
|
return state;
|
|
127
139
|
}
|
|
140
|
+
function useFragmentRefund(refundId, opts = {}) {
|
|
141
|
+
const { baseUrl } = useFrag();
|
|
142
|
+
if (refundId !== null && (typeof refundId !== "string" || refundId.length < 3)) {
|
|
143
|
+
throw new Error("[fragmentpay] useFragmentRefund: refundId must be a non-empty string or null");
|
|
144
|
+
}
|
|
145
|
+
const interval = opts.intervalMs ?? 3e3;
|
|
146
|
+
if (typeof interval !== "number" || interval < 500 || interval > 6e4) {
|
|
147
|
+
throw new Error("[fragmentpay] useFragmentRefund: intervalMs must be between 500 and 60000");
|
|
148
|
+
}
|
|
149
|
+
const [state, setState] = React.useState({ data: null, status: "idle", error: null });
|
|
150
|
+
React.useEffect(() => {
|
|
151
|
+
if (!refundId) return;
|
|
152
|
+
let alive = true;
|
|
153
|
+
let timer;
|
|
154
|
+
async function tick() {
|
|
155
|
+
try {
|
|
156
|
+
const res = await fetchWithRetry(
|
|
157
|
+
`${baseUrl}/api/public/refunds/${refundId}/status`,
|
|
158
|
+
{ maxRetries: 4 }
|
|
159
|
+
);
|
|
160
|
+
if (!res.ok) {
|
|
161
|
+
const retryAfter = parseRetryAfter(res.headers.get("retry-after")) ?? interval * 2;
|
|
162
|
+
throw Object.assign(new Error(`HTTP ${res.status}`), { retryAfter });
|
|
163
|
+
}
|
|
164
|
+
const raw = await res.json();
|
|
165
|
+
const data = { ...raw, phase: refundPhase(raw.status) };
|
|
166
|
+
if (!alive) return;
|
|
167
|
+
setState({ data, status: "ready", error: null });
|
|
168
|
+
if (!data.terminal) timer = setTimeout(tick, interval);
|
|
169
|
+
} catch (e) {
|
|
170
|
+
if (!alive) return;
|
|
171
|
+
const wait = e.retryAfter ?? interval * 2;
|
|
172
|
+
setState((s) => ({ ...s, status: "error", error: e.message }));
|
|
173
|
+
timer = setTimeout(tick, wait);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
setState({ data: null, status: "loading", error: null });
|
|
177
|
+
tick();
|
|
178
|
+
return () => {
|
|
179
|
+
alive = false;
|
|
180
|
+
clearTimeout(timer);
|
|
181
|
+
};
|
|
182
|
+
}, [refundId, baseUrl, interval]);
|
|
183
|
+
return state;
|
|
184
|
+
}
|
|
128
185
|
function FragmentPayCheckout({
|
|
129
186
|
intentId,
|
|
130
187
|
onSettled,
|
|
@@ -258,7 +315,9 @@ export {
|
|
|
258
315
|
FragmentPayCheckout,
|
|
259
316
|
FragmentPayProvider,
|
|
260
317
|
fetchWithRetry,
|
|
318
|
+
refundPhase,
|
|
261
319
|
useCreateIntent,
|
|
262
320
|
useFragmentIntent,
|
|
321
|
+
useFragmentRefund,
|
|
263
322
|
useFragmentTokens
|
|
264
323
|
};
|