@domino-sdk/relay 1.7.0 → 1.10.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.
Files changed (45) hide show
  1. package/dist/action-9Xl0StBg.d.ts +33 -0
  2. package/dist/{activity-Br6vyYze.d.ts → activity-C0O3g7VJ.d.ts} +9 -9
  3. package/dist/authoring.d.ts +12 -12
  4. package/dist/authoring.js +3 -3
  5. package/dist/{automatic-outcomes-C1Q9LrDb.d.ts → automatic-outcomes-kPIDv6X_.d.ts} +1 -1
  6. package/dist/avatar.d.ts +2 -2
  7. package/dist/browser.d.ts +9 -8
  8. package/dist/browser.js +8 -6
  9. package/dist/{capability-error-Bv996M-h.d.ts → capability-error-ty3SqD_b.d.ts} +1 -1
  10. package/dist/{chunk-KGJSKGKI.js → chunk-23JUD56J.js} +1119 -910
  11. package/dist/{chunk-ZOUEEK5L.js → chunk-7BRHUUVB.js} +83 -26
  12. package/dist/{chunk-C25TDFHN.js → chunk-BKLGWPPD.js} +48 -37
  13. package/dist/{chunk-6ON4RMEN.js → chunk-BUXNTVER.js} +1 -1
  14. package/dist/{chunk-BFZHJA2B.js → chunk-GEPSEVQO.js} +2 -2
  15. package/dist/chunk-GFAFH7XR.js +98 -0
  16. package/dist/{chunk-6RBF3UDA.js → chunk-GPS546KR.js} +232 -7
  17. package/dist/{chunk-5ECM6AWV.js → chunk-MMWTHVXW.js} +3 -3
  18. package/dist/chunk-N2HXMTVA.js +13 -0
  19. package/dist/{chunk-23QJ7WH4.js → chunk-QL77V77D.js} +1 -1
  20. package/dist/{chunk-GMPPLZKH.js → chunk-UIR6NSYZ.js} +243 -228
  21. package/dist/{chunk-JW4G3SY5.js → chunk-WRBPLXVP.js} +60 -47
  22. package/dist/{client-pfml_XAa.d.ts → client-Yq11HA_f.d.ts} +64 -43
  23. package/dist/{groups-BpWEqaPn.d.ts → groups-BK8ts2yK.d.ts} +94 -6
  24. package/dist/{images-BaKYd0fl.d.ts → images-aw6W7vFZ.d.ts} +2 -2
  25. package/dist/index.d.ts +10 -9
  26. package/dist/index.js +10 -5
  27. package/dist/internal.d.ts +3 -3
  28. package/dist/internal.js +5 -5
  29. package/dist/{offers-CYtal8jO.d.ts → offers-C2FANzrG.d.ts} +3 -3
  30. package/dist/{pages-CixTNnF4.d.ts → pages-D00JDZB-.d.ts} +70 -39
  31. package/dist/portal-proxy.js +8 -2
  32. package/dist/react/index.d.ts +203 -19
  33. package/dist/react/index.js +256 -113
  34. package/dist/{referral-reward-kinds-ClxAuCGx.d.ts → referral-reward-kinds-M3f0PdiR.d.ts} +2 -2
  35. package/dist/{schema-CQydLqw4.d.ts → schema-DEM8y8Fm.d.ts} +16 -16
  36. package/dist/schema.d.ts +11239 -13
  37. package/dist/schema.js +38 -6
  38. package/dist/server/index.d.ts +43693 -52
  39. package/dist/server/index.js +465 -53
  40. package/dist/{sign-in-options-CtXUFV7E.d.ts → sign-in-options-Coim0G1u.d.ts} +3 -3
  41. package/dist/{submission-input-CLefHTrj.d.ts → submission-input-BbBJTVlT.d.ts} +3 -3
  42. package/dist/util.d-w9f9t3ua.d.ts +5 -0
  43. package/dist/{wallet-YssWxGg8.d.ts → wallet-CDyo-U4n.d.ts} +1 -1
  44. package/package.json +1 -1
  45. package/dist/{profiles-D2aFcOxu.d.ts → profiles-BHMVj0kM.d.ts} +5 -5
@@ -8,20 +8,27 @@ import {
8
8
  discoverSolanaWallets,
9
9
  readSignInMethods,
10
10
  signInOptionsFrom
11
- } from "../chunk-BFZHJA2B.js";
12
- import "../chunk-ZOUEEK5L.js";
13
- import "../chunk-C25TDFHN.js";
11
+ } from "../chunk-GEPSEVQO.js";
12
+ import "../chunk-7BRHUUVB.js";
14
13
  import {
14
+ createRelayAction
15
+ } from "../chunk-GFAFH7XR.js";
16
+ import "../chunk-BKLGWPPD.js";
17
+ import {
18
+ RelayError,
15
19
  RelayErrorCode,
16
20
  asRelayError,
17
21
  isRelayError
18
- } from "../chunk-GMPPLZKH.js";
22
+ } from "../chunk-UIR6NSYZ.js";
19
23
  import "../chunk-6QJ3LADK.js";
20
- import "../chunk-NPGENI7K.js";
24
+ import {
25
+ isRequestError
26
+ } from "../chunk-NPGENI7K.js";
27
+ import "../chunk-N2HXMTVA.js";
21
28
  import {
22
29
  sessionMember
23
- } from "../chunk-6ON4RMEN.js";
24
- import "../chunk-KGJSKGKI.js";
30
+ } from "../chunk-BUXNTVER.js";
31
+ import "../chunk-23JUD56J.js";
25
32
 
26
33
  // src/react/activity.ts
27
34
  import {
@@ -385,13 +392,82 @@ function useActivity(options = {}) {
385
392
  return { ...value, refresh };
386
393
  }
387
394
 
395
+ // src/react/action.ts
396
+ import { useCallback as useCallback2, useRef as useRef2, useState as useState2 } from "react";
397
+ function useRelayAction(scope) {
398
+ const owner = useRef2({ scope, action: createRelayAction() });
399
+ const [state, setState] = useState2({
400
+ owner: owner.current,
401
+ busy: false,
402
+ error: null
403
+ });
404
+ if (owner.current.scope !== scope) {
405
+ owner.current = { scope, action: createRelayAction() };
406
+ }
407
+ const execute = useCallback2(
408
+ async (task) => {
409
+ const current2 = owner.current;
410
+ if (current2.action.busy) {
411
+ return { ok: false };
412
+ }
413
+ const result = task ? current2.action.run(task) : current2.action.retry();
414
+ setState({ owner: current2, busy: true, error: null });
415
+ try {
416
+ const value = await result;
417
+ if (owner.current === current2) {
418
+ setState({ owner: current2, busy: false, error: null });
419
+ }
420
+ return { ok: true, value };
421
+ } catch (caught) {
422
+ if (owner.current === current2) {
423
+ const cause = current2.action.error ?? caught;
424
+ const error = isRequestError(cause) && !isRelayError(cause) ? new RelayError(cause.message, {
425
+ kind: cause.kind,
426
+ status: cause.status,
427
+ code: cause.code,
428
+ uncertain: cause.uncertain,
429
+ operationId: cause.operationId,
430
+ replaySafe: cause.recovery === "replay",
431
+ retryAfter: cause.retryAfter,
432
+ cause
433
+ }) : asRelayError(cause);
434
+ setState({
435
+ owner: current2,
436
+ busy: false,
437
+ error
438
+ });
439
+ }
440
+ return { ok: false };
441
+ }
442
+ },
443
+ []
444
+ );
445
+ const retry = useCallback2(() => execute(), [execute]);
446
+ const settle = useCallback2(() => {
447
+ const current2 = owner.current;
448
+ if (!current2.action.settle()) {
449
+ return false;
450
+ }
451
+ setState({ owner: current2, busy: false, error: null });
452
+ return true;
453
+ }, []);
454
+ const current = state.owner === owner.current ? state : { busy: false, error: null };
455
+ return {
456
+ run: execute,
457
+ retry,
458
+ settle,
459
+ busy: current.busy,
460
+ error: current.error
461
+ };
462
+ }
463
+
388
464
  // src/react/provider.tsx
389
465
  import { useEffect as useEffect3, useMemo as useMemo2 } from "react";
390
466
 
391
467
  // src/react/experience.tsx
392
468
  import {
393
469
  createContext as createContext2,
394
- useCallback as useCallback2,
470
+ useCallback as useCallback3,
395
471
  useContext as useContext2,
396
472
  useMemo,
397
473
  useSyncExternalStore as useSyncExternalStore2
@@ -503,10 +579,10 @@ function watchRoleDeliveries(options) {
503
579
  }
504
580
 
505
581
  // src/react/use-role-deliveries.ts
506
- import { useEffect as useEffect2, useState as useState2 } from "react";
582
+ import { useEffect as useEffect2, useState as useState3 } from "react";
507
583
  var NONE = Object.freeze([]);
508
584
  function useRoleDeliveries(relay, member, completions) {
509
- const [state, setState] = useState2(null);
585
+ const [state, setState] = useState3(null);
510
586
  useEffect2(() => {
511
587
  if (!member || !completions) {
512
588
  return;
@@ -562,7 +638,7 @@ function useExperience() {
562
638
  const store = useStore();
563
639
  const experience = useExperienceSnapshot();
564
640
  const deliveries = useContext2(Deliveries);
565
- const refresh = useCallback2(() => store.refreshExperience(), [store]);
641
+ const refresh = useCallback3(() => store.refreshExperience(), [store]);
566
642
  return useMemo(
567
643
  () => ({ ...experience, refresh, deliveries }),
568
644
  [experience, refresh, deliveries]
@@ -1175,16 +1251,16 @@ function RelayProvider({
1175
1251
 
1176
1252
  // src/react/query.ts
1177
1253
  import {
1178
- useCallback as useCallback3,
1254
+ useCallback as useCallback4,
1179
1255
  useEffect as useEffect4,
1180
1256
  useLayoutEffect as useLayoutEffect2,
1181
1257
  useMemo as useMemo3,
1182
- useRef as useRef2,
1183
- useState as useState3,
1258
+ useRef as useRef3,
1259
+ useState as useState4,
1184
1260
  useSyncExternalStore as useSyncExternalStore3
1185
1261
  } from "react";
1186
1262
  function useLatest(value) {
1187
- const ref = useRef2(value);
1263
+ const ref = useRef3(value);
1188
1264
  useLayoutEffect2(() => {
1189
1265
  ref.current = value;
1190
1266
  });
@@ -1202,7 +1278,7 @@ function useCached(cache, key, read, options) {
1202
1278
  const hash = key ? hashKey(key) : null;
1203
1279
  const { intervalMs, refetchOnFocus } = options;
1204
1280
  const latest = useLatest({ key, read });
1205
- const subscribe = useCallback3(
1281
+ const subscribe = useCallback4(
1206
1282
  (listener) => {
1207
1283
  const { key: current } = latest.current;
1208
1284
  if (!cache || !current) {
@@ -1221,7 +1297,7 @@ function useCached(cache, key, read, options) {
1221
1297
  );
1222
1298
  const get = () => cache && key ? cache.snapshot(key) : LOADING;
1223
1299
  const snapshot = useSyncExternalStore3(subscribe, get, get);
1224
- const refresh = useCallback3(
1300
+ const refresh = useCallback4(
1225
1301
  () => cache && latest.current.key ? cache.refresh(latest.current.key) : Promise.resolve(),
1226
1302
  [cache, hash]
1227
1303
  );
@@ -1269,8 +1345,8 @@ function usePages(cache, key, read, options) {
1269
1345
  (context) => read(context),
1270
1346
  options
1271
1347
  );
1272
- const [more, setMore] = useState3(null);
1273
- const busy = useRef2(null);
1348
+ const [more, setMore] = useState4(null);
1349
+ const busy = useRef3(null);
1274
1350
  const latest = useLatest({ key, read, query });
1275
1351
  useEffect4(
1276
1352
  () => () => {
@@ -1279,7 +1355,7 @@ function usePages(cache, key, read, options) {
1279
1355
  },
1280
1356
  [cache, hash]
1281
1357
  );
1282
- const loadMore = useCallback3(async () => {
1358
+ const loadMore = useCallback4(async () => {
1283
1359
  const { key: current, read: reader, query: shown } = latest.current;
1284
1360
  if (!cache || !current || busy.current || shown.status !== "ready" || shown.data.nextCursor === null) {
1285
1361
  return;
@@ -1353,7 +1429,7 @@ function useMemberPages(key, read, options = {}) {
1353
1429
  }
1354
1430
  function useInvalidate() {
1355
1431
  const store = useStore();
1356
- return useCallback3((keys = []) => store.invalidate(keys), [store]);
1432
+ return useCallback4((keys = []) => store.invalidate(keys), [store]);
1357
1433
  }
1358
1434
  function useSession() {
1359
1435
  const store = useStore();
@@ -1369,22 +1445,22 @@ function useSession() {
1369
1445
  );
1370
1446
  }
1371
1447
  function useAction() {
1372
- const [busy, setBusy] = useState3(false);
1373
- const [actionError, setActionError] = useState3(null);
1374
- const run = useCallback3(async (task) => {
1375
- setBusy(true);
1376
- setActionError(null);
1377
- try {
1378
- await task();
1379
- return true;
1380
- } catch (cause) {
1381
- setActionError(relayError(cause));
1382
- return false;
1383
- } finally {
1384
- setBusy(false);
1385
- }
1386
- }, []);
1387
- return { busy, actionError, run };
1448
+ const session = useScopeSession();
1449
+ const store = useStore();
1450
+ const scope = useMemo3(() => ({ store, session }), [store, session]);
1451
+ const {
1452
+ run: execute,
1453
+ retry: replay,
1454
+ busy,
1455
+ error: actionError,
1456
+ settle
1457
+ } = useRelayAction(scope);
1458
+ const run = useCallback4(
1459
+ async (task) => (await execute(task)).ok,
1460
+ [execute]
1461
+ );
1462
+ const retry = useCallback4(async () => (await replay()).ok, [replay]);
1463
+ return { busy, actionError, run, retry, settle };
1388
1464
  }
1389
1465
  function useScopeSession() {
1390
1466
  const store = useStore();
@@ -1431,26 +1507,27 @@ function questGroups(experience, order = []) {
1431
1507
 
1432
1508
  // src/react/use-quest.ts
1433
1509
  import {
1434
- useCallback as useCallback4,
1510
+ useCallback as useCallback5,
1435
1511
  useEffect as useEffect5,
1436
1512
  useLayoutEffect as useLayoutEffect3,
1437
1513
  useMemo as useMemo4,
1438
- useRef as useRef3,
1439
- useState as useState4
1514
+ useRef as useRef4,
1515
+ useState as useState5
1440
1516
  } from "react";
1441
1517
  function useQuest(observed) {
1442
1518
  const store = useStore();
1443
1519
  const relay = store.client;
1444
- const [latest, setLatest] = useState4(null);
1445
- const [draft, setDraft] = useState4(null);
1446
- const [notice, setNotice] = useState4(null);
1447
- const [error, setError] = useState4(null);
1448
- const [busy, setBusy] = useState4(false);
1449
- const [discardedAttempt, setDiscardedAttempt] = useState4(null);
1450
- const [saved, setSaved] = useState4("none");
1451
- const [recoveryRevision, setRecoveryRevision] = useState4(0);
1452
- const [retired, setRetired] = useState4(false);
1453
- const [receipt, setReceipt] = useState4(null);
1520
+ const [latest, setLatest] = useState5(null);
1521
+ const [draft, setDraft] = useState5(null);
1522
+ const [notice, setNotice] = useState5(null);
1523
+ const [error, setError] = useState5(null);
1524
+ const [busy, setBusy] = useState5(false);
1525
+ const lock = useRef4(false);
1526
+ const [discardedAttempt, setDiscardedAttempt] = useState5(null);
1527
+ const [saved, setSaved] = useState5("none");
1528
+ const [recoveryRevision, setRecoveryRevision] = useState5(0);
1529
+ const [retired, setRetired] = useState5(false);
1530
+ const [receipt, setReceipt] = useState5(null);
1454
1531
  useEffect5(() => setLatest(null), [observed.release]);
1455
1532
  const view = latest ?? observed;
1456
1533
  const { quest, release } = view;
@@ -1474,8 +1551,12 @@ function useQuest(observed) {
1474
1551
  active = false;
1475
1552
  };
1476
1553
  }, [relay, quest, release, completed, attempt, busy, recoveryRevision]);
1477
- const run = useCallback4(
1554
+ const run = useCallback5(
1478
1555
  async (action) => {
1556
+ if (lock.current) {
1557
+ return;
1558
+ }
1559
+ lock.current = true;
1479
1560
  setBusy(true);
1480
1561
  setError(null);
1481
1562
  setNotice(null);
@@ -1494,19 +1575,24 @@ function useQuest(observed) {
1494
1575
  } catch (cause) {
1495
1576
  setError(asRelayError(cause, "Something went wrong."));
1496
1577
  } finally {
1578
+ lock.current = false;
1497
1579
  setBusy(false);
1498
1580
  setRecoveryRevision((revision) => revision + 1);
1499
1581
  }
1500
1582
  },
1501
1583
  [store]
1502
1584
  );
1503
- const shown = useRef3(view);
1585
+ const shown = useRef4(view);
1504
1586
  useLayoutEffect3(() => {
1505
1587
  shown.current = view;
1506
1588
  });
1507
1589
  const actions = useMemo4(
1508
1590
  () => ({
1509
1591
  restart: async () => {
1592
+ if (lock.current) {
1593
+ return;
1594
+ }
1595
+ lock.current = true;
1510
1596
  const current = shown.current;
1511
1597
  setBusy(true);
1512
1598
  setError(null);
@@ -1520,6 +1606,7 @@ function useQuest(observed) {
1520
1606
  } catch (cause) {
1521
1607
  setError(asRelayError(cause, "Could not start a new submission."));
1522
1608
  } finally {
1609
+ lock.current = false;
1523
1610
  setBusy(false);
1524
1611
  setRecoveryRevision((revision) => revision + 1);
1525
1612
  }
@@ -1605,10 +1692,10 @@ function useQuest(observed) {
1605
1692
  }
1606
1693
 
1607
1694
  // src/react/auth.ts
1608
- import { useCallback as useCallback5, useMemo as useMemo6, useRef as useRef4, useState as useState6 } from "react";
1695
+ import { useCallback as useCallback6, useMemo as useMemo6, useRef as useRef5, useState as useState7 } from "react";
1609
1696
 
1610
1697
  // src/react/wallets.ts
1611
- import { useEffect as useEffect6, useMemo as useMemo5, useState as useState5 } from "react";
1698
+ import { useEffect as useEffect6, useMemo as useMemo5, useState as useState6 } from "react";
1612
1699
  function useWallets() {
1613
1700
  const relay = useRelay();
1614
1701
  const invalidate = useInvalidate();
@@ -1618,7 +1705,7 @@ function useWallets() {
1618
1705
  (options) => relay.wallets.list(options),
1619
1706
  { refetchOnFocus: true }
1620
1707
  );
1621
- const { busy, actionError, run } = useAction();
1708
+ const { busy, actionError, run, retry, settle } = useAction();
1622
1709
  const actions = useMemo5(() => {
1623
1710
  const changed = () => void invalidate([relayKeys.wallets, relayKeys.experience]);
1624
1711
  return {
@@ -1637,8 +1724,8 @@ function useWallets() {
1637
1724
  };
1638
1725
  }, [relay, invalidate, session, run]);
1639
1726
  return useMemo5(
1640
- () => ({ ...query, busy, actionError, ...actions }),
1641
- [query, busy, actionError, actions]
1727
+ () => ({ ...query, busy, actionError, retry, settle, ...actions }),
1728
+ [query, busy, actionError, retry, settle, actions]
1642
1729
  );
1643
1730
  }
1644
1731
  function discoverChains(key) {
@@ -1648,7 +1735,7 @@ function discoverChains(key) {
1648
1735
  }
1649
1736
  function useWalletDiscovery(options = {}) {
1650
1737
  const chains = JSON.stringify(cosmosChainList(options.cosmos));
1651
- const [found, setFound] = useState5({ evm: [], solana: [], cosmos: [] });
1738
+ const [found, setFound] = useState6({ evm: [], solana: [], cosmos: [] });
1652
1739
  useEffect6(() => {
1653
1740
  let active = true;
1654
1741
  const solana = discoverSolanaWallets();
@@ -1671,7 +1758,7 @@ function useSignInWallets(networks, options = {}) {
1671
1758
  );
1672
1759
  const key = networks ? `${networks.join(" ")}
1673
1760
  ${chains}` : null;
1674
- const [found, setFound] = useState5(null);
1761
+ const [found, setFound] = useState6(null);
1675
1762
  useEffect6(() => {
1676
1763
  if (key === null) {
1677
1764
  return;
@@ -1705,16 +1792,21 @@ function useMe() {
1705
1792
  }
1706
1793
  function useSignIn() {
1707
1794
  const relay = useRelay();
1708
- const [challenge, setChallengeState] = useState6(null);
1709
- const latest = useRef4(null);
1710
- const [busy, setBusy] = useState6(false);
1711
- const [error, setError] = useState6(null);
1712
- const setChallenge = useCallback5((value) => {
1795
+ const [challenge, setChallengeState] = useState7(null);
1796
+ const latest = useRef5(null);
1797
+ const [busy, setBusy] = useState7(false);
1798
+ const lock = useRef5(false);
1799
+ const [error, setError] = useState7(null);
1800
+ const setChallenge = useCallback6((value) => {
1713
1801
  latest.current = value;
1714
1802
  setChallengeState(value);
1715
1803
  }, []);
1716
- const run = useCallback5(
1804
+ const run = useCallback6(
1717
1805
  async (task, fallback) => {
1806
+ if (lock.current) {
1807
+ return;
1808
+ }
1809
+ lock.current = true;
1718
1810
  setBusy(true);
1719
1811
  setError(null);
1720
1812
  try {
@@ -1722,19 +1814,20 @@ function useSignIn() {
1722
1814
  } catch (cause) {
1723
1815
  setError(asRelayError(cause, fallback));
1724
1816
  } finally {
1817
+ lock.current = false;
1725
1818
  setBusy(false);
1726
1819
  }
1727
1820
  },
1728
1821
  []
1729
1822
  );
1730
- const sendCode = useCallback5(
1823
+ const sendCode = useCallback6(
1731
1824
  (email) => run(async () => {
1732
1825
  setChallenge(null);
1733
1826
  setChallenge((await relay.auth.emailStart(email)).challenge);
1734
1827
  }, "Couldn't send a code. Check the address and try again."),
1735
1828
  [relay, run, setChallenge]
1736
1829
  );
1737
- const verifyCode = useCallback5(
1830
+ const verifyCode = useCallback6(
1738
1831
  (code) => run(async () => {
1739
1832
  const sent = latest.current;
1740
1833
  if (!sent) {
@@ -1745,18 +1838,18 @@ function useSignIn() {
1745
1838
  }, "That code didn't work. Check it, or request a new one."),
1746
1839
  [relay, run, setChallenge]
1747
1840
  );
1748
- const startOver = useCallback5(() => {
1841
+ const startOver = useCallback6(() => {
1749
1842
  setChallenge(null);
1750
1843
  setError(null);
1751
1844
  }, [setChallenge]);
1752
- const withProvider = useCallback5(
1845
+ const withProvider = useCallback6(
1753
1846
  (provider) => run(async () => {
1754
1847
  const { url } = await relay.auth.start(provider, "sign-in");
1755
1848
  window.location.assign(url);
1756
1849
  }, "Couldn't start sign-in. Try again."),
1757
1850
  [relay, run]
1758
1851
  );
1759
- const withWallet = useCallback5(
1852
+ const withWallet = useCallback6(
1760
1853
  (signer) => run(async () => {
1761
1854
  await relay.auth.wallet.signIn(signer);
1762
1855
  setChallenge(null);
@@ -1791,12 +1884,18 @@ function useSignIn() {
1791
1884
  }
1792
1885
  function useSignOut() {
1793
1886
  const store = useStore();
1794
- const [busy, setBusy] = useState6(false);
1795
- const signOut = useCallback5(async () => {
1887
+ const [busy, setBusy] = useState7(false);
1888
+ const lock = useRef5(false);
1889
+ const signOut = useCallback6(async () => {
1890
+ if (lock.current) {
1891
+ return;
1892
+ }
1893
+ lock.current = true;
1796
1894
  setBusy(true);
1797
1895
  try {
1798
1896
  await store.signOut();
1799
1897
  } finally {
1898
+ lock.current = false;
1800
1899
  setBusy(false);
1801
1900
  }
1802
1901
  }, [store]);
@@ -1871,7 +1970,7 @@ function useAccounts() {
1871
1970
  (options) => relay.auth.accounts(options),
1872
1971
  { refetchOnFocus: true }
1873
1972
  );
1874
- const { busy, actionError, run } = useAction();
1973
+ const { busy, actionError, run, retry, settle } = useAction();
1875
1974
  const actions = useMemo7(
1876
1975
  () => ({
1877
1976
  connect: (provider) => run(async () => {
@@ -1897,10 +1996,12 @@ function useAccounts() {
1897
1996
  ...query,
1898
1997
  busy,
1899
1998
  actionError,
1999
+ retry,
2000
+ settle,
1900
2001
  isConnected: (provider) => isConnected(accounts, provider),
1901
2002
  ...actions
1902
2003
  }),
1903
- [query, busy, actionError, accounts, actions]
2004
+ [query, busy, actionError, retry, settle, accounts, actions]
1904
2005
  );
1905
2006
  }
1906
2007
 
@@ -1916,11 +2017,11 @@ function useMyProfile() {
1916
2017
  (options) => relay.profiles.mine(options),
1917
2018
  { refetchOnFocus: true }
1918
2019
  );
1919
- const { busy, actionError, run } = useAction();
2020
+ const { busy, actionError, run, retry, settle } = useAction();
1920
2021
  const actions = useMemo8(() => {
1921
- const change = (task) => run(async () => {
2022
+ const change = (task) => run(async (actionId) => {
1922
2023
  const cache = store.scope?.cache;
1923
- const saved = await task();
2024
+ const saved = await task(actionId);
1924
2025
  cache?.set(MINE, saved);
1925
2026
  void cache?.invalidate([
1926
2027
  [...relayKeys.profiles, "get"],
@@ -1928,19 +2029,21 @@ function useMyProfile() {
1928
2029
  ]);
1929
2030
  });
1930
2031
  return {
1931
- update: (input) => change(() => relay.profiles.update(input, { session })),
2032
+ update: (input) => change(
2033
+ (actionId) => relay.profiles.update({ ...input, actionId }, { session })
2034
+ ),
1932
2035
  /** Uploads a JPEG, PNG or WebP of at most 5 MB as the avatar. */
1933
2036
  uploadAvatar: (file) => change(
1934
- () => relay.profiles.uploadAvatar(file, {
1935
- uploadId: crypto.randomUUID(),
2037
+ (actionId) => relay.profiles.uploadAvatar(file, {
2038
+ actionId,
1936
2039
  session
1937
2040
  })
1938
2041
  )
1939
2042
  };
1940
2043
  }, [relay, store, session, run]);
1941
2044
  return useMemo8(
1942
- () => ({ ...query, busy, actionError, ...actions }),
1943
- [query, busy, actionError, actions]
2045
+ () => ({ ...query, busy, actionError, retry, settle, ...actions }),
2046
+ [query, busy, actionError, retry, settle, actions]
1944
2047
  );
1945
2048
  }
1946
2049
  function useProfile(id, options = {}) {
@@ -1981,7 +2084,7 @@ function useProfileCompletions(profile, options = {}) {
1981
2084
  }
1982
2085
 
1983
2086
  // src/react/referrals.ts
1984
- import { useCallback as useCallback6, useEffect as useEffect7, useMemo as useMemo9, useRef as useRef5, useState as useState7 } from "react";
2087
+ import { useCallback as useCallback7, useEffect as useEffect7, useMemo as useMemo9, useRef as useRef6, useState as useState8 } from "react";
1985
2088
  var PENDING = "domino:pending-referral";
1986
2089
  var CODE = /^[a-zA-Z0-9_-]{1,100}$/;
1987
2090
  function captureReferralCode(param = "ref") {
@@ -2007,33 +2110,68 @@ function forgetReferralCode() {
2007
2110
  function useInvitation(param = "ref") {
2008
2111
  const relay = useRelay();
2009
2112
  const invalidate = useInvalidate();
2010
- const { member } = useSession();
2011
- const [state, setState] = useState7(() => {
2113
+ const signed = useSession();
2114
+ const { member } = signed;
2115
+ const session = signed.data?.id;
2116
+ const [state, setState] = useState8(() => {
2012
2117
  const code = captureReferralCode(param);
2013
2118
  return code ? { status: "pending", code } : { status: "none" };
2014
2119
  });
2015
- const started = useRef5(null);
2016
- const accept = useCallback6(
2120
+ const started = useRef6(null);
2121
+ const pending = useRef6({
2122
+ member,
2123
+ relay,
2124
+ session,
2125
+ code: "",
2126
+ action: createRelayAction()
2127
+ });
2128
+ if (pending.current.member !== member || pending.current.relay !== relay || pending.current.session !== session) {
2129
+ pending.current = {
2130
+ member,
2131
+ relay,
2132
+ session,
2133
+ code: "",
2134
+ action: createRelayAction()
2135
+ };
2136
+ }
2137
+ const accept = useCallback7(
2017
2138
  async (code) => {
2018
- setState({ status: "accepting", code });
2139
+ const owner = pending.current;
2140
+ if (owner.action.busy) {
2141
+ return;
2142
+ }
2143
+ if (!owner.action.error) {
2144
+ owner.code = code;
2145
+ }
2146
+ const logicalCode = owner.code;
2147
+ setState({ status: "accepting", code: logicalCode });
2019
2148
  try {
2020
- await relay.referrals.accept({ code, actionId: `accept-${code}` });
2149
+ await owner.action.run(
2150
+ (actionId) => relay.referrals.accept({ code, actionId }, { session })
2151
+ );
2152
+ if (pending.current !== owner) {
2153
+ return;
2154
+ }
2021
2155
  forgetReferralCode();
2022
- setState({ status: "accepted", code });
2156
+ setState({ status: "accepted", code: logicalCode });
2023
2157
  void invalidate([relayKeys.referrals, relayKeys.profiles]);
2024
- } catch (cause) {
2158
+ } catch (caught) {
2159
+ if (pending.current !== owner) {
2160
+ return;
2161
+ }
2162
+ const cause = owner.action.error ?? caught;
2025
2163
  const refused = isRelayError(cause) && (cause.kind === "http" && cause.status !== void 0 && cause.status >= 400 && cause.status < 500 && cause.status !== 429 || cause.code === RelayErrorCode.InvalidInput);
2026
2164
  if (refused) {
2027
2165
  forgetReferralCode();
2028
2166
  }
2029
2167
  setState({
2030
2168
  status: refused ? "rejected" : "failed",
2031
- code,
2169
+ code: logicalCode,
2032
2170
  error: asRelayError(cause, "That invitation code couldn't be used.")
2033
2171
  });
2034
2172
  }
2035
2173
  },
2036
- [relay, invalidate]
2174
+ [relay, invalidate, session]
2037
2175
  );
2038
2176
  useEffect7(() => {
2039
2177
  if (member && state.status === "pending" && started.current !== `${member}:${state.code}`) {
@@ -2108,7 +2246,7 @@ function useQuestOutcomes(query = {}) {
2108
2246
  }
2109
2247
 
2110
2248
  // src/react/offers.ts
2111
- import { useCallback as useCallback7, useState as useState8 } from "react";
2249
+ import { useCallback as useCallback8, useMemo as useMemo10 } from "react";
2112
2250
  function useOffers() {
2113
2251
  const relay = useRelay();
2114
2252
  return useRelayQuery(
@@ -2119,29 +2257,33 @@ function useOffers() {
2119
2257
  function useRedeemOffer() {
2120
2258
  const relay = useRelay();
2121
2259
  const invalidate = useInvalidate();
2122
- const [busy, setBusy] = useState8(false);
2123
- const [error, setError] = useState8(null);
2124
- const redeem = useCallback7(
2125
- async (offer) => {
2126
- if (busy) {
2127
- return null;
2128
- }
2129
- setBusy(true);
2130
- setError(null);
2131
- try {
2132
- const redemption = await relay.offers.redeem(offer);
2260
+ const session = useScopeSession();
2261
+ const scope = useMemo10(() => ({ relay, session }), [relay, session]);
2262
+ const {
2263
+ run,
2264
+ retry: replay,
2265
+ settle,
2266
+ busy,
2267
+ error
2268
+ } = useRelayAction(scope);
2269
+ const refresh = useCallback8(
2270
+ async (result) => {
2271
+ const redemption = result.ok ? result.value : null;
2272
+ if (redemption) {
2133
2273
  await invalidate([relayKeys.offers, relayKeys.balances]);
2134
- return redemption;
2135
- } catch (cause) {
2136
- setError(asRelayError(cause, "This offer could not be redeemed."));
2137
- return null;
2138
- } finally {
2139
- setBusy(false);
2140
2274
  }
2275
+ return redemption;
2141
2276
  },
2142
- [busy, invalidate, relay]
2277
+ [invalidate]
2278
+ );
2279
+ const redeem = useCallback8(
2280
+ (offer) => run(
2281
+ (actionId) => relay.offers.redeem(offer, { actionId }, { session })
2282
+ ).then(refresh),
2283
+ [run, relay, session, refresh]
2143
2284
  );
2144
- return { redeem, busy, error };
2285
+ const retry = useCallback8(() => replay().then(refresh), [replay, refresh]);
2286
+ return { redeem, retry, settle, busy, error };
2145
2287
  }
2146
2288
 
2147
2289
  // src/react/references.ts
@@ -2200,6 +2342,7 @@ export {
2200
2342
  useRedeemOffer,
2201
2343
  useReferralSummary,
2202
2344
  useRelay,
2345
+ useRelayAction,
2203
2346
  useRelayPages,
2204
2347
  useRelayQuery,
2205
2348
  useSession,