@unifold/headless-react 0.1.70-beta.1 → 0.1.71-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -5
- package/dist/index.js +29 -14
- package/dist/index.mjs +29 -14
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -71,13 +71,21 @@ function DepositUSDC({ externalUserId }: { externalUserId: string }) {
|
|
|
71
71
|
}
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
-
`useDeposit` drives an explicit
|
|
74
|
+
`useDeposit` drives an explicit **lifecycle** state machine:
|
|
75
75
|
|
|
76
76
|
```
|
|
77
|
-
idle → creating_addresses →
|
|
77
|
+
idle → creating_addresses → ready ⇄ processing
|
|
78
78
|
↘ error (fatal: address creation / invalid recipient)
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
+
`processing` is a live hint — “an execution is currently in flight” — and
|
|
82
|
+
toggles back to `ready` when everything settles. **Outcomes never
|
|
83
|
+
appear on the session status**: a session is an ongoing watcher that can
|
|
84
|
+
observe many executions, so a session-level "succeeded"/"failed" would
|
|
85
|
+
mislead the moment a second deposit arrives. Read outcomes from
|
|
86
|
+
`executions`/`latestExecution` statuses, the `direct_execution.succeeded` /
|
|
87
|
+
`.failed` events, or `waitForSuccess()`.
|
|
88
|
+
|
|
81
89
|
The headless SDK is deliberately **not IP-aware** — `useDeposit` never geo-gates
|
|
82
90
|
address creation. If you want the modal's region gate, opt in with
|
|
83
91
|
`useAllowedCountry` and gate your own UI on `isAllowed`.
|
|
@@ -108,9 +116,9 @@ For imperative flows, the session exposes `await`-style sugar over the event
|
|
|
108
116
|
stream (they only listen — neither starts nor stops the session):
|
|
109
117
|
|
|
110
118
|
```ts
|
|
111
|
-
// Generic primitive over the
|
|
112
|
-
await session.waitForStatus('processing');
|
|
113
|
-
await session.waitForStatus(
|
|
119
|
+
// Generic primitive over the lifecycle state machine:
|
|
120
|
+
await session.waitForStatus('processing'); // live activity detected
|
|
121
|
+
await session.waitForStatus('ready'); // addresses ready / all settled
|
|
114
122
|
|
|
115
123
|
// The 90% case — mirrors beginDeposit()'s promise contract
|
|
116
124
|
// (resolve on success, reject on failure):
|
package/dist/index.js
CHANGED
|
@@ -77,6 +77,8 @@ function useDeposit(options) {
|
|
|
77
77
|
(0, import_react2.useEffect)(() => {
|
|
78
78
|
callbacksRef.current = options;
|
|
79
79
|
});
|
|
80
|
+
const autoStartRef = (0, import_react2.useRef)(autoStart);
|
|
81
|
+
autoStartRef.current = autoStart;
|
|
80
82
|
const [session, setSession] = (0, import_react2.useState)(null);
|
|
81
83
|
const sessionKey = [
|
|
82
84
|
publishableKey,
|
|
@@ -143,7 +145,7 @@ function useDeposit(options) {
|
|
|
143
145
|
}
|
|
144
146
|
});
|
|
145
147
|
setSession(nextSession);
|
|
146
|
-
if (
|
|
148
|
+
if (autoStartRef.current) {
|
|
147
149
|
void nextSession.start();
|
|
148
150
|
}
|
|
149
151
|
return () => {
|
|
@@ -151,7 +153,7 @@ function useDeposit(options) {
|
|
|
151
153
|
offStatus();
|
|
152
154
|
nextSession.destroy();
|
|
153
155
|
};
|
|
154
|
-
}, [sessionKey
|
|
156
|
+
}, [sessionKey]);
|
|
155
157
|
const subscribe = (0, import_react2.useCallback)(
|
|
156
158
|
(listener) => session ? session.subscribe(listener) : () => {
|
|
157
159
|
},
|
|
@@ -226,7 +228,9 @@ function useDepositAddresses(options) {
|
|
|
226
228
|
publishableKey
|
|
227
229
|
),
|
|
228
230
|
select: (response) => response.data.map(import_core3.mapWalletToDepositAddress),
|
|
229
|
-
|
|
231
|
+
// When a destination is supplied it must be complete — never issue a
|
|
232
|
+
// create call with a partially-filled destination.
|
|
233
|
+
enabled: enabled && !!externalUserId && !!publishableKey && (!destination || !!destination.chainType && !!destination.chainId && !!destination.tokenAddress && !!destination.recipientAddress),
|
|
230
234
|
staleTime: 1e3 * 60 * 60,
|
|
231
235
|
// 1 hour — wallets don't change once created
|
|
232
236
|
gcTime: 1e3 * 60 * 60 * 24,
|
|
@@ -244,11 +248,12 @@ var import_react_provider4 = require("@unifold/react-provider");
|
|
|
244
248
|
function useSupportedDepositTokens(options = {}) {
|
|
245
249
|
const { publishableKey } = (0, import_react_provider4.useUnifold)();
|
|
246
250
|
const { destination, productType, enabled = true } = options;
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
251
|
+
const completeDestination = destination?.chainType && destination?.chainId && destination?.tokenAddress ? destination : void 0;
|
|
252
|
+
const apiOptions = completeDestination || productType ? {
|
|
253
|
+
...completeDestination ? {
|
|
254
|
+
destination_token_address: completeDestination.tokenAddress,
|
|
255
|
+
destination_chain_id: completeDestination.chainId,
|
|
256
|
+
destination_chain_type: completeDestination.chainType
|
|
252
257
|
} : {},
|
|
253
258
|
...productType ? { product_type: productType } : {}
|
|
254
259
|
} : void 0;
|
|
@@ -279,7 +284,12 @@ var import_core5 = require("@unifold/core");
|
|
|
279
284
|
var import_react_provider5 = require("@unifold/react-provider");
|
|
280
285
|
function useExecutions(options) {
|
|
281
286
|
const { publishableKey } = (0, import_react_provider5.useUnifold)();
|
|
282
|
-
const {
|
|
287
|
+
const {
|
|
288
|
+
externalUserId,
|
|
289
|
+
refetchInterval = false,
|
|
290
|
+
enabled = true,
|
|
291
|
+
actionType = import_core5.ActionType.Deposit
|
|
292
|
+
} = options;
|
|
283
293
|
return (0, import_react_query3.useQuery)({
|
|
284
294
|
// Key parity with @unifold/ui-react's useExecutions.
|
|
285
295
|
queryKey: ["unifold", "executions", actionType, externalUserId, publishableKey],
|
|
@@ -358,7 +368,8 @@ var import_react_provider7 = require("@unifold/react-provider");
|
|
|
358
368
|
function useAddressValidation(options) {
|
|
359
369
|
const { publishableKey } = (0, import_react_provider7.useUnifold)();
|
|
360
370
|
const { recipientAddress, destination, enabled = true } = options;
|
|
361
|
-
const
|
|
371
|
+
const hasCompleteDestination = !!destination?.chainType && !!destination?.chainId && !!destination?.tokenAddress;
|
|
372
|
+
const shouldValidate = enabled && !!publishableKey && !!recipientAddress && hasCompleteDestination;
|
|
362
373
|
const { data, isLoading, error } = (0, import_react_query5.useQuery)({
|
|
363
374
|
// Key parity with @unifold/ui-react's useAddressValidation.
|
|
364
375
|
queryKey: [
|
|
@@ -379,11 +390,15 @@ function useAddressValidation(options) {
|
|
|
379
390
|
publishableKey
|
|
380
391
|
),
|
|
381
392
|
enabled: shouldValidate,
|
|
382
|
-
|
|
383
|
-
|
|
393
|
+
// Address validity is EXTERNAL state that can flip without the query key
|
|
394
|
+
// changing (e.g. an Algorand recipient opts in to the asset). Always
|
|
395
|
+
// revalidate on mount and never serve a stale verdict — otherwise a user
|
|
396
|
+
// who fixes the problem still sees "invalid" until a cache window expires.
|
|
397
|
+
refetchOnMount: "always",
|
|
398
|
+
refetchOnReconnect: true,
|
|
384
399
|
refetchOnWindowFocus: false,
|
|
385
|
-
staleTime:
|
|
386
|
-
gcTime: 1e3 * 60 *
|
|
400
|
+
staleTime: 0,
|
|
401
|
+
gcTime: 1e3 * 60 * 5
|
|
387
402
|
});
|
|
388
403
|
if (!shouldValidate) {
|
|
389
404
|
return { isValid: null, failureCode: null, metadata: null, isLoading: false, error: null };
|
package/dist/index.mjs
CHANGED
|
@@ -41,6 +41,8 @@ function useDeposit(options) {
|
|
|
41
41
|
useEffect(() => {
|
|
42
42
|
callbacksRef.current = options;
|
|
43
43
|
});
|
|
44
|
+
const autoStartRef = useRef(autoStart);
|
|
45
|
+
autoStartRef.current = autoStart;
|
|
44
46
|
const [session, setSession] = useState(null);
|
|
45
47
|
const sessionKey = [
|
|
46
48
|
publishableKey,
|
|
@@ -107,7 +109,7 @@ function useDeposit(options) {
|
|
|
107
109
|
}
|
|
108
110
|
});
|
|
109
111
|
setSession(nextSession);
|
|
110
|
-
if (
|
|
112
|
+
if (autoStartRef.current) {
|
|
111
113
|
void nextSession.start();
|
|
112
114
|
}
|
|
113
115
|
return () => {
|
|
@@ -115,7 +117,7 @@ function useDeposit(options) {
|
|
|
115
117
|
offStatus();
|
|
116
118
|
nextSession.destroy();
|
|
117
119
|
};
|
|
118
|
-
}, [sessionKey
|
|
120
|
+
}, [sessionKey]);
|
|
119
121
|
const subscribe = useCallback(
|
|
120
122
|
(listener) => session ? session.subscribe(listener) : () => {
|
|
121
123
|
},
|
|
@@ -193,7 +195,9 @@ function useDepositAddresses(options) {
|
|
|
193
195
|
publishableKey
|
|
194
196
|
),
|
|
195
197
|
select: (response) => response.data.map(mapWalletToDepositAddress),
|
|
196
|
-
|
|
198
|
+
// When a destination is supplied it must be complete — never issue a
|
|
199
|
+
// create call with a partially-filled destination.
|
|
200
|
+
enabled: enabled && !!externalUserId && !!publishableKey && (!destination || !!destination.chainType && !!destination.chainId && !!destination.tokenAddress && !!destination.recipientAddress),
|
|
197
201
|
staleTime: 1e3 * 60 * 60,
|
|
198
202
|
// 1 hour — wallets don't change once created
|
|
199
203
|
gcTime: 1e3 * 60 * 60 * 24,
|
|
@@ -213,11 +217,12 @@ import { useUnifold as useUnifold4 } from "@unifold/react-provider";
|
|
|
213
217
|
function useSupportedDepositTokens(options = {}) {
|
|
214
218
|
const { publishableKey } = useUnifold4();
|
|
215
219
|
const { destination, productType, enabled = true } = options;
|
|
216
|
-
const
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
220
|
+
const completeDestination = destination?.chainType && destination?.chainId && destination?.tokenAddress ? destination : void 0;
|
|
221
|
+
const apiOptions = completeDestination || productType ? {
|
|
222
|
+
...completeDestination ? {
|
|
223
|
+
destination_token_address: completeDestination.tokenAddress,
|
|
224
|
+
destination_chain_id: completeDestination.chainId,
|
|
225
|
+
destination_chain_type: completeDestination.chainType
|
|
221
226
|
} : {},
|
|
222
227
|
...productType ? { product_type: productType } : {}
|
|
223
228
|
} : void 0;
|
|
@@ -252,7 +257,12 @@ import {
|
|
|
252
257
|
import { useUnifold as useUnifold5 } from "@unifold/react-provider";
|
|
253
258
|
function useExecutions(options) {
|
|
254
259
|
const { publishableKey } = useUnifold5();
|
|
255
|
-
const {
|
|
260
|
+
const {
|
|
261
|
+
externalUserId,
|
|
262
|
+
refetchInterval = false,
|
|
263
|
+
enabled = true,
|
|
264
|
+
actionType = ActionType.Deposit
|
|
265
|
+
} = options;
|
|
256
266
|
return useQuery3({
|
|
257
267
|
// Key parity with @unifold/ui-react's useExecutions.
|
|
258
268
|
queryKey: ["unifold", "executions", actionType, externalUserId, publishableKey],
|
|
@@ -333,7 +343,8 @@ import { useUnifold as useUnifold7 } from "@unifold/react-provider";
|
|
|
333
343
|
function useAddressValidation(options) {
|
|
334
344
|
const { publishableKey } = useUnifold7();
|
|
335
345
|
const { recipientAddress, destination, enabled = true } = options;
|
|
336
|
-
const
|
|
346
|
+
const hasCompleteDestination = !!destination?.chainType && !!destination?.chainId && !!destination?.tokenAddress;
|
|
347
|
+
const shouldValidate = enabled && !!publishableKey && !!recipientAddress && hasCompleteDestination;
|
|
337
348
|
const { data, isLoading, error } = useQuery5({
|
|
338
349
|
// Key parity with @unifold/ui-react's useAddressValidation.
|
|
339
350
|
queryKey: [
|
|
@@ -354,11 +365,15 @@ function useAddressValidation(options) {
|
|
|
354
365
|
publishableKey
|
|
355
366
|
),
|
|
356
367
|
enabled: shouldValidate,
|
|
357
|
-
|
|
358
|
-
|
|
368
|
+
// Address validity is EXTERNAL state that can flip without the query key
|
|
369
|
+
// changing (e.g. an Algorand recipient opts in to the asset). Always
|
|
370
|
+
// revalidate on mount and never serve a stale verdict — otherwise a user
|
|
371
|
+
// who fixes the problem still sees "invalid" until a cache window expires.
|
|
372
|
+
refetchOnMount: "always",
|
|
373
|
+
refetchOnReconnect: true,
|
|
359
374
|
refetchOnWindowFocus: false,
|
|
360
|
-
staleTime:
|
|
361
|
-
gcTime: 1e3 * 60 *
|
|
375
|
+
staleTime: 0,
|
|
376
|
+
gcTime: 1e3 * 60 * 5
|
|
362
377
|
});
|
|
363
378
|
if (!shouldValidate) {
|
|
364
379
|
return { isValid: null, failureCode: null, metadata: null, isLoading: false, error: null };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unifold/headless-react",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.71-beta.1",
|
|
4
4
|
"description": "Unifold Headless React SDK - hooks-only (no UI) crypto deposit flows",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@tanstack/react-query": "^5.90.11",
|
|
24
|
-
"@unifold/core": "0.1.
|
|
25
|
-
"@unifold/react-provider": "0.1.
|
|
24
|
+
"@unifold/core": "0.1.71-beta.1",
|
|
25
|
+
"@unifold/react-provider": "0.1.71-beta.1"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/react": "^19.0.0",
|