@domino-sdk/relay 1.61.0 → 1.62.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 (80) hide show
  1. package/CHANGELOG.md +156 -8
  2. package/README.md +3 -2
  3. package/dist/{schema-CZ6Rj0ZF.d.ts → accounts-CCqCKCVx.d.ts} +3127 -1764
  4. package/dist/action-9Xl0StBg.d.ts +33 -0
  5. package/dist/{integrations-B3y36OaB.d.ts → analytics-BwAKLi7O.d.ts} +347 -57
  6. package/dist/{attempt-captures-DYnJVkfg.d.ts → attempt-captures-Cm-5G0PC.d.ts} +1 -1
  7. package/dist/authoring.d.ts +130 -42
  8. package/dist/authoring.js +112 -37
  9. package/dist/{automatic-outcomes-If88LR9f.d.ts → automatic-outcomes-pAsOyIVp.d.ts} +5 -1
  10. package/dist/avatar.d.ts +1 -1
  11. package/dist/browser.d.ts +15 -11
  12. package/dist/browser.js +15 -11
  13. package/dist/{announcements-CHx3-HBw.d.ts → capability-error-DFMwSuSf.d.ts} +161 -4
  14. package/dist/{pages-K7-KjSXw.d.ts → catalog--ZIlskAo.d.ts} +39 -561
  15. package/dist/{chunk-DYXDZFKA.js → chunk-3KLC4AMA.js} +37 -11
  16. package/dist/{chunk-XBV2CK2H.js → chunk-3PYYGFSB.js} +14 -2
  17. package/dist/{chunk-RHBS5FJL.js → chunk-5TEYFX6X.js} +2 -2
  18. package/dist/chunk-6WCIWXUV.js +31 -0
  19. package/dist/chunk-CICDIBOF.js +373 -0
  20. package/dist/{chunk-MHPKEVEW.js → chunk-CZFXGGEK.js} +5 -0
  21. package/dist/chunk-D26YNACF.js +320 -0
  22. package/dist/{chunk-5I54XBK2.js → chunk-E6IKQHTX.js} +2 -2
  23. package/dist/chunk-FWLQ5XCS.js +21 -0
  24. package/dist/{chunk-SKGTNTLF.js → chunk-GKIFABGN.js} +150 -61
  25. package/dist/chunk-GTDW453U.js +522 -0
  26. package/dist/{chunk-VURRFVNP.js → chunk-HTZHBTIL.js} +69 -27
  27. package/dist/chunk-K2KS3JLY.js +188 -0
  28. package/dist/{chunk-ZDJLPN4L.js → chunk-MK425RXJ.js} +3143 -3209
  29. package/dist/{chunk-L77O64I4.js → chunk-QYPMPWVX.js} +1 -1
  30. package/dist/chunk-UAKYDVT3.js +565 -0
  31. package/dist/{chunk-DHXDBAJF.js → chunk-UPQPUJOU.js} +36 -123
  32. package/dist/{chunk-24I4R732.js → chunk-UW5232GG.js} +34 -19
  33. package/dist/chunk-WSBYWVTZ.js +717 -0
  34. package/dist/{chunk-PPB7HALD.js → chunk-XJFYAXET.js} +9 -8
  35. package/dist/{chunk-7A4J67ZL.js → chunk-XNKSSE32.js} +1 -1
  36. package/dist/{chunk-QEAS4ZGS.js → chunk-Y322OTCH.js} +1 -1
  37. package/dist/{client-C51w7fMb.d.ts → client-B-hbHX30.d.ts} +109 -40
  38. package/dist/{deployments-kWoHFaqj.d.ts → deployments-M4OHn7G3.d.ts} +407 -18
  39. package/dist/identity-integration-3mX6b5iH.d.ts +1241 -0
  40. package/dist/index.d.ts +13 -11
  41. package/dist/index.js +14 -11
  42. package/dist/internal.d.ts +14 -12
  43. package/dist/internal.js +26 -14
  44. package/dist/{offers-BoV4ryUc.d.ts → offers-DhAtss4_.d.ts} +21 -4
  45. package/dist/pages-B8q8Y_dQ.d.ts +715 -0
  46. package/dist/{participant-activity-DHL8QYks.d.ts → participant-activity-D-Drp24G.d.ts} +16 -3
  47. package/dist/portal-proxy.d.ts +59 -2
  48. package/dist/portal-proxy.js +109 -23
  49. package/dist/react/index.d.ts +206 -26
  50. package/dist/react/index.js +153 -25
  51. package/dist/{action-DBzILFx9.d.ts → request-error-D_dUPLwo.d.ts} +1 -31
  52. package/dist/runtime/authoring.js +1 -1
  53. package/dist/runtime/chunks/Y4OAVXFR.js +1 -0
  54. package/dist/runtime/manifest.json +3 -3
  55. package/dist/runtime/schema.js +1 -1
  56. package/dist/schema.d.ts +154 -30
  57. package/dist/schema.js +126 -75
  58. package/dist/server/index.d.ts +14 -12
  59. package/dist/server/index.js +2137 -1633
  60. package/dist/sign-in-providers-BkjcDsFF.d.ts +39 -0
  61. package/dist/submission-input-DHGKhXfp.d.ts +342 -0
  62. package/dist/{telegram-browser-BUceZIGZ.d.ts → telegram-browser-BCE7zdOb.d.ts} +46 -6
  63. package/dist/telegram.d.ts +64 -0
  64. package/dist/telegram.js +23 -0
  65. package/dist/testing.d.ts +112 -15
  66. package/dist/testing.js +321 -16
  67. package/dist/tracker-data-Hb1uQnk5.d.ts +1855 -0
  68. package/dist/{transport-BrX9pIGN.d.ts → transport-DkhX2Cbs.d.ts} +5764 -2217
  69. package/dist/{wallet-CIqFoxdm.d.ts → wallet-DTO7SXj7.d.ts} +20 -7
  70. package/package.json +5 -1
  71. package/dist/accounts-DoabriBX.d.ts +0 -306
  72. package/dist/capability-error-DufwG3G0.d.ts +0 -159
  73. package/dist/chunk-3Y3L2F54.js +0 -982
  74. package/dist/chunk-EN3M5Z4J.js +0 -13
  75. package/dist/chunk-QNUHWK7R.js +0 -602
  76. package/dist/chunk-SE4PFJPT.js +0 -247
  77. package/dist/groups-CqcA2Ycs.d.ts +0 -2827
  78. package/dist/runtime/chunks/5QVFB4TU.js +0 -1
  79. package/dist/submission-input-C54Q8yAD.d.ts +0 -146
  80. package/dist/x-D1PGi8Sq.d.ts +0 -331
@@ -7,22 +7,26 @@ import {
7
7
  discoverSignInWallets,
8
8
  discoverSolanaWallets,
9
9
  readSignInMethods,
10
- signInOptionsFrom,
10
+ signInOptionsFrom
11
+ } from "../chunk-UW5232GG.js";
12
+ import {
11
13
  telegramMiniAppInitData
12
- } from "../chunk-24I4R732.js";
13
- import "../chunk-SKGTNTLF.js";
14
+ } from "../chunk-FWLQ5XCS.js";
15
+ import "../chunk-GKIFABGN.js";
14
16
  import {
15
17
  createRelayAction
16
- } from "../chunk-QEAS4ZGS.js";
17
- import "../chunk-QNUHWK7R.js";
18
- import "../chunk-3Y3L2F54.js";
19
- import "../chunk-SE4PFJPT.js";
18
+ } from "../chunk-Y322OTCH.js";
19
+ import "../chunk-6WCIWXUV.js";
20
+ import "../chunk-CICDIBOF.js";
21
+ import "../chunk-D26YNACF.js";
22
+ import "../chunk-GTDW453U.js";
23
+ import "../chunk-WSBYWVTZ.js";
20
24
  import "../chunk-KDR2VAJP.js";
21
- import "../chunk-XBV2CK2H.js";
22
- import "../chunk-EN3M5Z4J.js";
25
+ import "../chunk-3PYYGFSB.js";
23
26
  import {
24
27
  sessionMember
25
- } from "../chunk-PPB7HALD.js";
28
+ } from "../chunk-XJFYAXET.js";
29
+ import "../chunk-MK425RXJ.js";
26
30
  import {
27
31
  RelayError,
28
32
  RelayErrorCode,
@@ -30,7 +34,7 @@ import {
30
34
  clientError,
31
35
  isRelayError,
32
36
  isRequestError
33
- } from "../chunk-ZDJLPN4L.js";
37
+ } from "../chunk-K2KS3JLY.js";
34
38
 
35
39
  // src/react/context.ts
36
40
  import { createContext, useContext } from "react";
@@ -52,12 +56,14 @@ var relayKeys = {
52
56
  experience: ["experience"],
53
57
  /** `useMe`. */
54
58
  me: ["me"],
55
- /** `useAccounts`. */
59
+ /** `useAccounts`, `useAccount`, `useTelegramAccount`, `useCreatorAccounts`. */
56
60
  accounts: ["accounts"],
57
61
  /** `useWallets`. */
58
62
  wallets: ["wallets"],
59
63
  /** `useMyProfile`, `useProfile`, `useProfileCompletions`, `useProfileReferral`. */
60
64
  profiles: ["profiles"],
65
+ /** `useConsent`. */
66
+ consent: ["consent"],
61
67
  /** `useLeaderboard`, `useLeaderboardPlacement`, `useLeaderboardHistory`. */
62
68
  leaderboards: ["leaderboards"],
63
69
  /** `useReferralSummary`. */
@@ -624,8 +630,11 @@ var ActivityFeed = class {
624
630
  };
625
631
 
626
632
  // src/react/role-delivery.ts
633
+ function grantsRole({ action }) {
634
+ return typeof action !== "string" || action === "grant-role";
635
+ }
627
636
  function sanitizeDeliveries(deliveries) {
628
- return deliveries.map(({ quest, status, revokedAt, reconciliation }) => ({
637
+ return deliveries.filter(grantsRole).map(({ quest, status, revokedAt, reconciliation }) => ({
629
638
  quest,
630
639
  status: reconciliation ? reconciliation.status === "granted" ? "delivered" : reconciliation.status : revokedAt ? "revoked" : status
631
640
  }));
@@ -1912,7 +1921,7 @@ function useBadgeCatalog() {
1912
1921
  const relay = useRelay();
1913
1922
  return useRelayQuery(
1914
1923
  [...relayKeys.badges, "catalog"],
1915
- (options) => relay.badges.list(options)
1924
+ async (options) => (await relay.badges.catalog(options)).items
1916
1925
  );
1917
1926
  }
1918
1927
  function useBadges() {
@@ -2664,6 +2673,10 @@ function useSignIn() {
2664
2673
  sendCode,
2665
2674
  verifyCode,
2666
2675
  startOver,
2676
+ /**
2677
+ * Leaves for the provider's consent screen: any of `providers().signInProviders`, Telegram
2678
+ * included.
2679
+ */
2667
2680
  withProvider,
2668
2681
  /**
2669
2682
  * Signs in, or signs up, with a wallet; the wallet asks the participant to sign a message. A
@@ -2671,11 +2684,15 @@ function useSignIn() {
2671
2684
  * to another account in it, or locking it, signs out.
2672
2685
  */
2673
2686
  withWallet,
2674
- /** Leaves for Telegram Login, where the platform configured it. */
2687
+ /**
2688
+ * Leaves for Telegram Login, where the platform configured it.
2689
+ *
2690
+ * @deprecated Use `withProvider("telegram")`. Removed in 2.0.0.
2691
+ */
2675
2692
  withTelegram,
2676
2693
  /**
2677
2694
  * Signs in, or signs up, inside a Telegram Mini App the project enabled, with its launch data
2678
- * (`telegramMiniAppInitData()`).
2695
+ * (`telegramMiniAppInitData()` from `@domino-sdk/relay/telegram`).
2679
2696
  */
2680
2697
  withTelegramMiniApp
2681
2698
  }),
@@ -2739,7 +2756,7 @@ function useSignInOptions(input = {}) {
2739
2756
  if (!methods) {
2740
2757
  return null;
2741
2758
  }
2742
- if (!wallets && methods.providers.length === 0 && !methods.email && !methods.telegram?.login) {
2759
+ if (!wallets && methods.providers.length === 0 && !methods.signInProviders?.length && !methods.email && !methods.telegram?.login) {
2743
2760
  return null;
2744
2761
  }
2745
2762
  return signInOptionsFrom(methods, wallets ?? [], {
@@ -2747,6 +2764,7 @@ function useSignInOptions(input = {}) {
2747
2764
  walletsPending: !wallets,
2748
2765
  actions: {
2749
2766
  oauth: withProvider,
2767
+ provider: withProvider,
2750
2768
  sendCode,
2751
2769
  verifyCode,
2752
2770
  wallet: withWallet,
@@ -2767,6 +2785,7 @@ function useSignInOptions(input = {}) {
2767
2785
  return useMemo7(
2768
2786
  () => ({
2769
2787
  options: built?.options ?? null,
2788
+ signInProviders: built?.signInProviders ?? null,
2770
2789
  unavailable: built?.unavailable ?? NONE_UNAVAILABLE,
2771
2790
  telegram: built?.telegram ?? null,
2772
2791
  methodsError,
@@ -2782,7 +2801,7 @@ function useSignInOptions(input = {}) {
2782
2801
  }
2783
2802
 
2784
2803
  // src/react/accounts.ts
2785
- import { useMemo as useMemo8 } from "react";
2804
+ import { useCallback as useCallback8, useMemo as useMemo8 } from "react";
2786
2805
  function isConnected(accounts, provider) {
2787
2806
  return Boolean(
2788
2807
  accounts?.some(
@@ -2846,6 +2865,67 @@ function useAccounts() {
2846
2865
  ]
2847
2866
  );
2848
2867
  }
2868
+ function useAccount(provider) {
2869
+ const relay = useRelay();
2870
+ const invalidate = useInvalidate();
2871
+ const session = useScopeSession();
2872
+ const select = useCallback8(
2873
+ (accounts) => accounts.find((account2) => account2.provider === provider) ?? null,
2874
+ [provider]
2875
+ );
2876
+ const query = useMemberQuery(
2877
+ [...relayKeys.accounts, "sign-in"],
2878
+ (options) => relay.auth.signInAccounts(options),
2879
+ { refetchOnFocus: true, select }
2880
+ );
2881
+ const { isPending, actionError: actionError2, resetAction, run, retry, settle } = useAction();
2882
+ const actions = useMemo8(
2883
+ () => ({
2884
+ connect: () => run(async () => {
2885
+ const { url } = await relay.auth.start(
2886
+ { provider, mode: "connect" },
2887
+ { session }
2888
+ );
2889
+ window.location.assign(url);
2890
+ }),
2891
+ disconnect: () => run(async () => {
2892
+ await relay.auth.disconnect(provider, { session });
2893
+ void invalidate([
2894
+ relayKeys.accounts,
2895
+ relayKeys.experience,
2896
+ relayKeys.profiles
2897
+ ]);
2898
+ })
2899
+ }),
2900
+ [relay, invalidate, session, run, provider]
2901
+ );
2902
+ const account = query.data;
2903
+ return useMemo8(
2904
+ () => ({
2905
+ ...query,
2906
+ isPending,
2907
+ actionError: actionError2,
2908
+ resetAction,
2909
+ retry,
2910
+ settle,
2911
+ /** True when the account can be used to verify quests right now. */
2912
+ isConnected: Boolean(
2913
+ account?.configured && account.status === "connected"
2914
+ ),
2915
+ ...actions
2916
+ }),
2917
+ [
2918
+ query,
2919
+ isPending,
2920
+ actionError2,
2921
+ resetAction,
2922
+ retry,
2923
+ settle,
2924
+ account,
2925
+ actions
2926
+ ]
2927
+ );
2928
+ }
2849
2929
  function useTelegramAccount() {
2850
2930
  const relay = useRelay();
2851
2931
  const invalidate = useInvalidate();
@@ -3049,8 +3129,54 @@ function useProfileCompletions(profile, options = {}) {
3049
3129
  );
3050
3130
  }
3051
3131
 
3132
+ // src/react/consent.ts
3133
+ import { useMemo as useMemo10 } from "react";
3134
+ function useConsent() {
3135
+ const relay = useRelay();
3136
+ const store = useStore();
3137
+ const session = useScopeSession();
3138
+ const query = useMemberQuery(
3139
+ relayKeys.consent,
3140
+ (options) => relay.consent.get(options)
3141
+ );
3142
+ const { isPending, actionError: actionError2, resetAction, run, retry, settle } = useAction();
3143
+ const actions = useMemo10(() => {
3144
+ const change = (channel, granted, wording) => run(async (actionId) => {
3145
+ const cache = store.scope?.cache;
3146
+ await relay.consent.set(
3147
+ {
3148
+ actionId,
3149
+ channel,
3150
+ granted,
3151
+ ...wording === void 0 ? {} : { wording }
3152
+ },
3153
+ { session }
3154
+ );
3155
+ void cache?.invalidate([relayKeys.consent]);
3156
+ });
3157
+ return {
3158
+ /** Records the member's opt-in on `channel`, with the wording they saw. */
3159
+ grant: (channel, wording) => change(channel, true, wording),
3160
+ /** Records the member's opt-out on `channel`, with the wording they saw if there was any. */
3161
+ withdraw: (channel, wording) => change(channel, false, wording)
3162
+ };
3163
+ }, [relay, store, session, run]);
3164
+ return useMemo10(
3165
+ () => ({
3166
+ ...query,
3167
+ isPending,
3168
+ actionError: actionError2,
3169
+ resetAction,
3170
+ retry,
3171
+ settle,
3172
+ ...actions
3173
+ }),
3174
+ [query, isPending, actionError2, resetAction, retry, settle, actions]
3175
+ );
3176
+ }
3177
+
3052
3178
  // src/react/referrals.ts
3053
- import { useCallback as useCallback8, useEffect as useEffect7, useMemo as useMemo10, useRef as useRef7, useState as useState8 } from "react";
3179
+ import { useCallback as useCallback9, useEffect as useEffect7, useMemo as useMemo11, useRef as useRef7, useState as useState8 } from "react";
3054
3180
  var PENDING = "domino:pending-referral";
3055
3181
  var CODE = /^[a-zA-Z0-9_-]{1,100}$/;
3056
3182
  function captureReferralCode(param = "ref") {
@@ -3100,7 +3226,7 @@ function useInvitation(param = "ref") {
3100
3226
  action: createRelayAction()
3101
3227
  };
3102
3228
  }
3103
- const accept = useCallback8(
3229
+ const accept = useCallback9(
3104
3230
  async (code) => {
3105
3231
  const owner = pending.current;
3106
3232
  if (owner.action.busy) {
@@ -3145,7 +3271,7 @@ function useInvitation(param = "ref") {
3145
3271
  void accept(state.code);
3146
3272
  }
3147
3273
  }, [member, state, accept]);
3148
- return useMemo10(() => ({ invitation: state, accept }), [state, accept]);
3274
+ return useMemo11(() => ({ invitation: state, accept }), [state, accept]);
3149
3275
  }
3150
3276
  function useReferralSummary(options = {}) {
3151
3277
  const relay = useRelay();
@@ -3155,7 +3281,7 @@ function useReferralSummary(options = {}) {
3155
3281
  (request) => relay.referrals.summary(request),
3156
3282
  { intervalMs }
3157
3283
  );
3158
- return useMemo10(() => {
3284
+ return useMemo11(() => {
3159
3285
  let link = null;
3160
3286
  if (query.data && typeof window !== "undefined") {
3161
3287
  const url = new URL(path, window.location.origin);
@@ -3222,7 +3348,7 @@ function useQuestOutcomes(query = {}) {
3222
3348
  }
3223
3349
 
3224
3350
  // src/react/offers.ts
3225
- import { useCallback as useCallback9, useMemo as useMemo11 } from "react";
3351
+ import { useCallback as useCallback10, useMemo as useMemo12 } from "react";
3226
3352
  function useOffers() {
3227
3353
  const relay = useRelay();
3228
3354
  return useRelayQuery(
@@ -3237,11 +3363,11 @@ function useRedeemOffer() {
3237
3363
  { invalidates: [relayKeys.offers, relayKeys.balances] }
3238
3364
  );
3239
3365
  const { mutateAsync } = mutation;
3240
- const redeem = useCallback9(
3366
+ const redeem = useCallback10(
3241
3367
  (offer) => mutateAsync(offer).catch(() => null),
3242
3368
  [mutateAsync]
3243
3369
  );
3244
- return useMemo11(
3370
+ return useMemo12(
3245
3371
  () => ({ ...mutation, redeem, retry: replay, busy: mutation.isPending }),
3246
3372
  [mutation, redeem, replay]
3247
3373
  );
@@ -3281,11 +3407,13 @@ export {
3281
3407
  roleDeliveryLabel,
3282
3408
  roleDeliveryStatus,
3283
3409
  telegramMiniAppInitData,
3410
+ useAccount,
3284
3411
  useAccounts,
3285
3412
  useActivity,
3286
3413
  useBadgeCatalog,
3287
3414
  useBadges,
3288
3415
  useBalances,
3416
+ useConsent,
3289
3417
  useCreatorAccounts,
3290
3418
  useDeliveries,
3291
3419
  useEntitlements,
@@ -64,34 +64,4 @@ declare class RequestError extends Error {
64
64
  constructor(message: string, details: RequestErrorDetails);
65
65
  }
66
66
 
67
- /** SDK input convenience; the wire request always carries a key. */
68
- type OptionalActionId<T> = T extends {
69
- actionId: string;
70
- } ? Omit<T, "actionId"> & {
71
- actionId?: string;
72
- } : never;
73
- /** One logical write. Keep this object until its outcome is definite. */
74
- type RelayAction<T> = {
75
- /** The pending write's key, also available on its uncertain error as `operationId`. */
76
- readonly actionId: string | undefined;
77
- readonly busy: boolean;
78
- readonly error: RequestError | undefined;
79
- /**
80
- * Starts a write with a generated key. While an uncertain write is pending, replays its saved
81
- * callback instead of accepting a different write. Concurrent calls share one request.
82
- * Put refreshes and other follow-up work outside the callback.
83
- */
84
- run(task: (actionId: string) => Promise<T>): Promise<T>;
85
- /** Replays the exact pending callback and key, only when the error's recovery is `replay`. */
86
- retry(): Promise<T>;
87
- /** Acknowledge an authoritative, definite outcome after reconciliation. Refuses while busy. */
88
- settle(): boolean;
89
- };
90
- /**
91
- * Owns a mutation key across uncertain answers. A definite success or refusal ends the action;
92
- * the next `run` gets a new key. `reconcile` failures stay pending and cannot be replayed.
93
- * In-memory only: persist the key yourself if recovery must survive a reload or process restart.
94
- */
95
- declare function createRelayAction<T = unknown>(): RelayAction<T>;
96
-
97
- export { type OptionalActionId as O, type RelayAction as R, RequestError as a, type RequestErrorDetails as b, type RequestErrorKind as c, type RequestRecovery as d, createRelayAction as e, isRequestError as i };
67
+ export { RequestError as R, type RequestErrorDetails as a, type RequestErrorKind as b, type RequestRecovery as c, isRequestError as i };
@@ -1 +1 @@
1
- import{$b as je,$c as Ze,Ad as He,B as j,Bd as E,C as se,Cd as Je,D as ce,De as G,E as ie,F as ue,Fb as xe,Fe as L,G as de,Gd as q,H as le,Hb as Me,Hh as gt,I as me,Ie as nt,Ig as dt,J as ge,Jd as Nt,Jg as lt,Kc as Oe,Kg as H,Nc as Ne,Oc as Lt,Pc as Ke,Pf as ct,Qd as y,Qe as _,Rb as ze,Rc as Rt,Rd as Xe,Sb as $e,Sc as Tt,Sd as C,Se as ot,Tc as Ue,Ua as U,Ud as Kt,Uh as $,Va as be,Vb as Ae,Wa as V,Wc as Bt,Wf as it,X as he,Xa as ye,Xc as Ve,Y as pe,Yc as Dt,Zc as Pt,_e as st,a as B,aa as fe,ba as D,cd as It,dd as Ot,ea as ke,fa as K,fd as Qe,ga as we,gd as We,gh as mt,gi as Qt,hi as ht,ii as pt,ja as ve,je as Ut,ji as ft,kc as Le,ke as Vt,ki as kt,lc as Re,le as Zt,mb as Se,me as Ye,nc as Te,ne as et,oc as Be,pb as Ee,pc as De,pd as Q,pe as tt,qc as Pe,qd as P,r as ee,re as rt,s as te,sc as jt,t as re,tc as Ie,td as W,te as at,u as ae,ub as qe,ud as F,v as ne,vc as Z,vd as Fe,vi as Wt,w as oe,wi as Ft,yb as Ce,yd as Ge,yg as ut,yi as Gt,zd as _e}from"./chunks/5QVFB4TU.js";import{Cb as z,Ec as A,Kb as J,Pd as At,fc as X,ic as N,jc as Y,va as O,wc as T}from"./chunks/EWU4OKSY.js";function wt(e){if(!Number.isInteger(e)||e<0||e>255)throw new Error("Token decimals must be an integer from 0 to 255")}function _t(e,r){wt(r);let t=/^(\d+)(?:\.(\d+))?$/.exec(e.trim());if(!t)throw new Error(`Use a decimal amount such as "1.5", not "${e}"`);let[,a,n=""]=t,c=n.replace(/0+$/,"");if(c.length>r)throw new Error(`"${e}" has more than ${r} decimal places, which this token cannot hold`);return BigInt(a+c.padEnd(r,"0"))}function Ht(e,r){wt(r);let t=typeof e=="bigint"?e:BigInt(e),a=t<0n?"-":"",n=(t<0n?-t:t).toString().padStart(r+1,"0"),c=n.slice(0,n.length-r),i=n.slice(n.length-r).replace(/0+$/,"");return a+c+(i?"."+i:"")}function bt(e,r={}){let{trigger:t,completion:a,requires:n,performance:c,retryCooldownMs:i,completionCooldownMs:u,authorBudgets:o=[]}=e,g=t.kind==="automatic"?t.tracker:void 0,l=g?.content===!0;if(c&&!l)throw new Error("Performance requires a content quest");if(!g&&o.length)throw new Error('A budget with scope "author" counts per tracker record author: use it only on a quest with a tracker trigger');if(l){if(a.kind!=="keyed")throw new Error("Content quests complete once per content item");if(g.beneficiary!=="author"||g.on!=="new-record")throw new Error("A content quest pays each content item's author and fires on its first observation")}if(i!==void 0&&(t.kind!=="manual"||t.actor==="staff"))throw new Error("A retry cooldown applies only to quests members submit themselves");if(u!==void 0){if(t.kind!=="manual"||t.actor==="staff")throw new Error("A completion cooldown applies only to quests members submit themselves");if(a.kind==="once")throw new Error("A completion cooldown needs a quest members can complete more than once: this one completes once per member")}if(t.kind==="automatic"&&!g){if(!r.template&&n.length===0)throw new Error("Automatic quests need at least one prerequisite");if(a.kind!=="once")throw new Error("Prerequisite-only automatic quests complete once")}}var Jt=["author"],Xt=["author","messageAuthor"];function yt(e){if(!ve(e))return[];switch(e.kind){case"x-search":return he;case"discord-messages":return Jt;case"discord-reactions":return Xt;case"custom":return["author",...e.accounts??[]]}}var vt=new Map;function Yt(e){let r=e.kind==="discord-messages"&&e.text?"messages-text":e.kind,t=vt.get(r);return t||(t=j(r==="messages-text"?ae:r==="discord-messages"?re:ne),vt.set(r,t)),t}function St(e){switch(e.kind){case"x-search":return;case"discord-messages":case"discord-reactions":return Yt(e);case"custom":return e.data}}function qr(e){return y("badge",$("Badge",ut,e))}function Cr(e){return y("ledger",$("Point ledger",it,e))}function xr(e){let{target:r,ledger:t,...a}=e,n=dt.parse({...a,qualifiedBy:e.qualifiedBy.key,balance:C(t)}),c=T(A(e.metrics),H.shape.target);return{key:n.key,describe:()=>n,score(i){let u=lt.parse(i);return H.parse({target:r({metrics:c.parse(u.metrics)}),baseline:r({metrics:c.parse(u.baseline)})})}}}var tr=e=>{if("timeZone"in e)throw new Error("streak() no longer takes a timeZone. Set the project timezone with calendar.timeZone in relay.json or in Console settings.");return Se.strict().parse({kind:"streak",...e})},Mr=e=>be.brand().parse({kind:"count",count:e}),zr=(e,r={})=>V.brand().parse({kind:"calendar",period:e,...r}),$r=({days:e})=>V.brand().parse({kind:"rolling",durationMs:e*864e5}),Ar=e=>({kind:"quest",quest:e});function jr(e){let{qualification:r,inviterGroup:t,milestones:a,bonuses:n,...c}=e,i=$("Referral",gt,{...c,qualification:r.kind==="quest"?{kind:"quest",quest:r.quest.key}:r,...t?{inviterGroup:B.parse(t.key)}:{},milestones:a?.map(({key:u,...o})=>({...o,id:q({key:u,...o})})),bonuses:n?.map(({key:u,ledger:o,quests:g,...l})=>({...l,id:q({key:u,...l}),balance:C(o),quests:g?.map(M=>M.key)}))});return y("referral",i)}function Lr(e={}){return{kind:"earned",...e}}function Rr(e){let{ledger:r,group:t,score:a,settle:n,...c}=e,i=n?.pool,u=$("Leaderboard",mt,{...c,...n?{settle:{...n,prizes:n.prizes??[],...i?{pool:{...i,...i.ledger===void 0?{}:{ledger:C(i.ledger)}}}:{}}}:{},balance:C(r),...t?{group:B.parse(t.key)}:{},score:a?.kind==="earned"?{...a,quests:a.quests?.map(o=>o.key)}:a});return y("leaderboard",u)}var Tr={provider:"x",search:e=>fe.parse({kind:"x-search",...e})};function R(e,r){let{data:t,content:a,...n}=r??{};if(a!==void 0){if(t!==void 0)throw new Error(`customSource("${e}") takes data or content, not both: a content source's records carry { body, metrics }`);if(!Et(a.body))throw new Error(`customSource("${e}") needs a content body schema: customSource(namespace, { content: { body: z.object({ ... }), metrics: ["likes"] } })`);let c=[...a.metrics??[]];for(let i of c)pe.parse(i);return D.parse({kind:"custom",namespace:e,...n,data:j(N({body:a.body,metrics:Y(Object.fromEntries(c.map(i=>[i,z().int().safe().nonnegative().optional()]))).optional()})),content:{metrics:c}})}if(!Et(t))throw new Error(`customSource("${e}") needs a data schema: customSource(namespace, { data: z.object({ ... }) }) describes each record's data`);return D.parse({kind:"custom",namespace:e,...n,data:j(t)})}function Et(e){return typeof e=="object"&&e!==null&&"_zod"in e}function Br(e){return y("tracker",$("Tracker",we,e))}function rr(e={}){return ee.parse({kind:"discord-messages",...e.text?{text:!0}:{}})}function ar(){return te.parse({kind:"discord-reactions"})}var Dr={provider:"discord",grantRole:e=>oe.parse({kind:"integration",provider:"discord",action:"grant-role",roleId:e}),postMessage(e){return Be.parse({provider:"discord",action:"post-message",...e})},messages:rr,reactions:ar,roles(e={}){return P.parse({provider:"discord",resource:"role",assignable:e.assignable??!1})},channels(e={}){return P.parse({provider:"discord",resource:"channel",types:e.types??["text","announcement"],...e.postable?{postable:!0}:{}})}},Pr={postMessage(e){return Te.parse({provider:"telegram",action:"post-message",...e})},messages(){return R(de,{identities:["member"],data:Re})},reactions(){return R(ue,{identities:["member"],accounts:["messageAuthor"],data:Le})}},Ir={shorts(){return R(le,{identities:["member"],content:{body:ht,metrics:pt}})}},Or={videos(){return R(me,{identities:["member"],content:{body:ft,metrics:kt}})}};function nr(e){let{chain:r,token:t}=e,a=t===void 0?null:t;if(a!==null&&typeof a!="string")throw new Error("wallet.balances() takes the token as a string");if(r==="solana"||r===Z){if(a!==null&&!Pe.safeParse(a).success)throw new Error("wallet.balances() on Solana takes an SPL or Token-2022 mint address (base58)");return{chain:Z,token:a}}if(typeof r=="string"&&Oe(r)){if(a!==null&&!/^0x[0-9a-fA-F]{40}$/.test(a))throw new Error("wallet.balances() on an EVM chain takes an ERC-20 contract address: 0x and 40 hex digits");return{chain:r,token:a}}if(typeof r=="string"&&/^cosmos:[-_a-zA-Z0-9]{1,32}$/.test(r)){if(a===null||!Ie.safeParse(a).success)throw new Error("wallet.balances() on a Cosmos chain takes a bank denomination such as uatom");return{chain:r,token:a}}throw new Error('wallet.balances() reads "solana", an EVM chain such as "eip155:8453" or a Cosmos network such as "cosmos:cosmoshub-4"')}var Nr={balances(e){let r=nr(e),t=R(ge,{identities:["wallet"],data:Ne});return D.parse({...t,balance:r})}},Kr=()=>({provider:"domino",resource:"point-ledger"});function p(e,r){return r}var Ur={pointLedger(e){let r={...e,kind:"point-ledger",default:e.default?B.parse(e.default.key):""};return p("point-ledger",Xe.prefault(r.default).meta(r))},datetime(e){let r={...e,kind:"datetime",default:W.parse(e.default)};return p("datetime",W.default(r.default).meta(r))},resource(e){let r={...e,source:P.parse(e.source),kind:"resource",default:F.parse(e.default??"")};return p("resource",F.default(r.default).meta(r))},quiz(e){let r=Q.parse(e.default);return p("quiz",Q.default(r).meta({...e,default:r,kind:"quiz"}))},text(e){let r={...e,kind:"text",minLength:e.minLength??1,maxLength:e.maxLength??2e3,multiline:e.multiline??!1};return p("text",O().min(r.minLength).max(r.maxLength).default(r.default).meta(r))},telegramChat(e){let r={...e,kind:"text",default:e.default??"",minLength:0,maxLength:64,multiline:!1,picker:"telegram-chat"};return p("text",O().max(r.maxLength).default(r.default).meta(r))},amount(e){if(!Ge(e.default))throw new Error(`settings.amount() takes a base-unit integer string as its default, not "${e.default}"`);let r={...e,kind:"text",minLength:1,maxLength:100,multiline:!1,picker:"amount"};return p("text",E(r).default(r.default).meta(r))},chain(e){if(!_e(e.default))throw new Error(`settings.chain() takes "solana" or an EVM chain ID such as "eip155:8453" as its default, not "${e.default}"`);let r={...e,kind:"text",minLength:1,maxLength:64,multiline:!1,picker:"chain"};return p("text",E(r).transform(t=>t).default(r.default).meta(r))},nft(e){if(!Ke(e.default))throw new Error(`settings.nft() takes an NFT collection such as "eip155:1/erc721:0x\u2026" as its default, not "${e.default}"`);let r={...e,kind:"text",minLength:1,maxLength:200,multiline:!1,picker:"nft"};return p("text",E(r).transform(t=>t).default(r.default).meta(r))},contractCall(e){if(!Ue(e.default))throw new Error(`settings.contractCall() takes a contract call such as "eip155:8453:0x\u2026 function stakedOf(address) view returns (uint256)" as its default, not "${e.default}"`);let r={...e,kind:"text",minLength:1,maxLength:400,multiline:!1,picker:"contract-call"};return p("text",E(r).transform(t=>t).default(r.default).meta(r))},contractEvent(e){if(!Ve(e.default))throw new Error(`settings.contractEvent() takes a contract event such as "eip155:1:0x\u2026 Transfer(address indexed from, address indexed to, uint256 value)" as its default, not "${e.default}"`);let r={...e,kind:"text",minLength:1,maxLength:1e3,multiline:!1,picker:"contract-event"};return p("text",E(r).transform(t=>t).default(r.default).meta(r))},solanaProgram(e){if(!Ze(e.default))throw new Error(`settings.solanaProgram() takes a Solana program address such as "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4" as its default, not "${e.default}"`);let r={...e,kind:"text",minLength:32,maxLength:44,multiline:!1,picker:"solana-program"};return p("text",E(r).transform(t=>t).default(r.default).meta(r))},integer(e){return p("integer",z().int().min(e.min).max(e.max).default(e.default).meta({...e,kind:"integer"}))},boolean(e){return p("boolean",J().default(e.default).meta({...e,kind:"boolean"}))},choice(e){return p("choice",A(e.options).default(e.default).meta({...e,kind:"choice"}))},object(e){return N(e).strict()}};function Ct(e,r){let t=e.balanceChanges.find(a=>a.mint===r);return t?BigInt(t.delta):0n}function Zr(e,r){let t=Ct(e,r);return t>0n?t.toString():"0"}function Qr(e,r){let t=Ct(e,r);return t<0n?(-t).toString():"0"}function Wr(e,r={}){let t=e.balanceChanges.filter(n=>BigInt(n.delta)>0n),a=e.balanceChanges.filter(n=>BigInt(n.delta)<0n);return t.some(n=>(r.into===void 0||n.mint===r.into)&&a.some(c=>c.mint!==n.mint&&(r.from===void 0||c.mint===r.from)))}function Fr(e,r){return e.programs.includes(r)}function Gr(e,r){return e.instructions?.find(t=>t.name===r)?.args??null}var _r=e=>rt(e.key,e.name),Hr=e=>at(e.key,e.title),Jr=(e,r)=>Ye.parse({kind:"points",balance:C(e),amount:r}),Xr={text:(e={})=>({input:"text",constraints:Qe.parse(e)}),url:(e={})=>({input:"url",constraints:We.parse(e)}),photo:()=>"photo",quiz:()=>"quiz"};function Yr(e){if(e?.actor&&e.input!==void 0)throw new Error('manual() cannot combine actor "staff" with input: staff-captured evidence is not supported. Use manual({ actor: "staff" }) for a staff confirmation, or manual({ input }) for evidence the participant submits.');return typeof e?.input=="object"?{kind:"manual",...e.input}:{kind:"manual",input:e?.input??"none",...e?.actor?{actor:e.actor}:{}}}var xt=new WeakMap,Mt=new WeakMap;function zt(e,r){let{tracker:t,beneficiary:a="author",on:n,where:c,enrollment:i,since:u,historical:o,content:g}=e;if(!t?.source)throw new Error(r==="automatic"?"automatic() takes no argument, or { tracker } with a tracker handle from defineTracker":"content() takes { tracker } with a tracker handle from defineTracker");let{source:l}=t;if(!ke(l))throw new Error('Tracker triggers need attributable records: declare customSource(namespace, { identities: ["wallet"] }) or other identity kinds');if(g&&!K(l))throw new Error(`content() needs a tracker whose source has content: x.search(), or customSource(namespace, { content: { body, metrics } }). Tracker "${t.key}" has none; use automatic({ tracker }) instead.`);if(u==="enrollment"&&i!=="required")throw new Error(`${r}() counts from enrollment only on a quest that requires it: add enrollment: "required"`);let M=yt(l);if(!M.includes(a))throw new Error(l.kind==="custom"?`Tracker "${t.key}" has no "${a}" account: declare it in customSource(namespace, { accounts: ["${a}"] })`:`Tracker "${t.key}" pays ${M.map(S=>`"${S}"`).join(" or ")}, not "${a}"`);let s=Ce.parse({tracker:t.key,source:l.kind,on:g?"new-record":n??Ee(l.kind),...c?{where:c}:{},beneficiary:a,...i==="required"?{enrollment:i}:{},...u&&u!=="activation"?{since:u}:{},...o&&o!==(g?"claim":"staff")?{historical:o}:{},...g?{content:g}:{}}),d=St(l),f=d?ie(d,s.where):null;if(f)throw new Error(f);let b={kind:"automatic",tracker:s};d&&xt.set(b,d);let w=K(l);return w&&Mt.set(b,w.metrics),b}function ea(e){return e?zt(e,"automatic"):{kind:"automatic"}}function ta(e){if(e&&typeof e=="object"&&"source"in e&&"key"in e&&!("tracker"in e))throw new Error("content() takes { tracker }: write content({ tracker: posts }) instead of content(posts)");return zt({...e,content:!0},"content")}function or(e){let{key:r,cost:t,...a}=e,n={...a,id:q(e),cost:typeof t=="number"?t:{balance:C(t.ledger)}};return a.scope==="author"?$e.parse(n):ze.parse(n)}var ra=or,sr=(e=[])=>e.filter(r=>r.scope==="author"),cr=e=>({kind:"keyed",key:e}),ir=e=>{let{distinct:r,...t}=e;return{...ye.parse({kind:"progress",window:{kind:"lifetime"},...t}),distinct:r}},aa=()=>({kind:"untracked"}),na=()=>({kind:"staff-handover"}),oa=()=>({kind:"automatic"});function sa(e){let{key:r,tiers:t,...a}=e,n=q(e),c=et.parse({id:n,...a,tiers:t.map(({key:i,...u})=>({...u,id:q({key:i,...u})}))});return y("tiered-reward",{key:c.id,tier:i=>tt.parse({kind:"tier",reward:c,tier:i})})}var ur=()=>({kind:"once"});function dr(e={}){return{kind:"accept",...e}}function lr(e){return{kind:"review",...e}}var x={accept:dr,defer:e=>({kind:"defer",...e}),progress:e=>({kind:"progress",...e}),reject:e=>({kind:"reject",...e}),review:lr};function qt(e){let r=e.kind==="reject"&&e.code!==void 0?Me(e.code):null;if(r)throw new Error(r)}var ca={quiz(e,r={}){let t=st.parse(e),a=Object.keys(t),n=z().int().min(1).max(a.length).parse(r.minimumCorrect??a.length);return async({input:c})=>{let i=Object.keys(c.answers).length===a.length&&a.every(o=>Object.hasOwn(c.answers,o)),u=a.filter(o=>c.answers[o]===t[o]).length;return i&&u>=n?x.accept():x.reject({reason:"Review your answers and try again."})}},photo(e){return async r=>{let t=e(r),a=await r.review.photo({image:r.input.photo,criteria:t.criteria});return a.kind==="unclear"?t.unclear==="human-review"?x.review({reason:a.reason}):x.reject({reason:a.reason}):a.kind==="pass"?x.accept():x.reject({reason:a.reason})}}},mr={once:ur,keyed:cr,streak:tr,progress:ir};function $t(e){return function(t){let a=q(t),n=[...new Set((t.integrations??[]).map(s=>Ae.parse(s.provider)))],c=t.trigger.kind==="automatic"&&t.trigger.tracker?.content===!0,i=t.trigger.kind==="automatic"&&t.trigger.tracker!==void 0,u=t.completion,o=typeof u=="function"?u(mr):u;if(c&&o!==void 0)throw new Error("A content quest completes once per content item: remove its completion");if(!c&&o===void 0)throw new Error("A quest needs a completion, such as once(), keyed(...), streak(...) or progress(...)");let g=sr(t.budgets);if(bt({trigger:t.trigger,completion:o??{kind:"keyed"},requires:t.requires??[],authorBudgets:g,performance:t.performance?U.parse({metrics:t.performance.metrics,maxAgeMs:t.performance.maxAgeMs}):void 0,...t.retryCooldownMs===void 0?{}:{retryCooldownMs:t.retryCooldownMs},...t.completionCooldownMs===void 0?{}:{completionCooldownMs:t.completionCooldownMs}},{template:e}),t.retryCooldownMs!==void 0&&!G.safeParse(t.retryCooldownMs).success)throw new Error("retryCooldownMs must be whole milliseconds from 1000 (one second) to 604800000 (seven days)");if(t.completionCooldownMs!==void 0&&!G.safeParse(t.completionCooldownMs).success)throw new Error("completionCooldownMs must be whole milliseconds from 1000 (one second) to 604800000 (seven days)");if(t.performance){let s=Mt.get(t.trigger)??[],d=t.performance.metrics.filter(f=>!s.includes(f));if(d.length)throw new Error(`The tracker's source does not measure ${d.join(", ")}`)}if(t.trigger.kind==="manual"&&t.trigger.input!=="none"&&!t.evaluate)throw new Error("Evidence quests require an evaluator");let l=Object.fromEntries(Object.entries(t.settings.shape).map(([s,d])=>{let f=Fe.safeParse(d.meta());if(!f.success)throw new Error(`Setting "${s}" is not a quest setting: build it with a settings builder, such as settings.integer({ label, default, min, max })`);return[s,f.data]}));for(let s of qe(t.trigger.kind==="automatic"?t.trigger.tracker?.where:void 0))if(!He(l[s]))throw new Error(`The tracker filter compares with setting "${s}", which is not an integer or amount setting`);function M(s){let d=t.settings.parse(s),f=Je(l,d),b=nt.parse(typeof t.rewards=="function"?t.rewards({settings:d}):t.rewards),w=X(De).max(3,"A quest posts at most three announcements").parse((typeof t.announcements=="function"?t.announcements({settings:d}):t.announcements)??[]),S=t.trigger.kind==="automatic"&&t.trigger.tracker!==void 0;for(let m of w){let v=je(m.text),I="segments"in v&&v.segments.some(k=>k.kind==="placeholder"&&k.name==="author");if(!S&&I)throw new Error("An announcement names {author} only on a quest with an automatic tracker trigger");if(!S&&m.replyToTriggeringMessage)throw new Error("An announcement replies to the triggering message only on a quest with an automatic tracker trigger")}let h=[...b.flatMap(m=>m.kind==="integration"?[m.provider]:[]),...w.flatMap(m=>m.provider==="discord"?["discord"]:[]),...Object.values(l).flatMap(m=>m.kind==="resource"&&m.source.provider!=="domino"?[m.source.provider]:[])];for(let m of h)if(!n.includes(m))throw new Error(`Declare the ${m} integration on this quest`);return ot.parse({quest:a,evaluatorProtocol:_,title:typeof t.title=="function"?t.title({settings:d}):t.title,presentation:t.presentation?.({settings:d})??{},fields:l,values:f,rewards:b,...w.length?{announcements:w}:{},humanReview:t.review?.({settings:d})?.enabled??!0,trigger:t.trigger,...t.performance?{performance:U.parse({metrics:t.performance.metrics,maxAgeMs:t.performance.maxAgeMs})}:{},integrations:n,completion:o?o.kind==="progress"?{kind:o.kind,goal:o.goal,window:o.window,repeat:o.repeat}:o.kind==="streak"?o:{kind:o.kind}:{kind:"keyed"},visibility:t.visibility??"visible",profile:t.profile??{visible:!1},budgets:(t.budgets??[]).filter(m=>m.scope!=="author"),...g.length?{authorBudgets:g}:{},requires:t.requires??[],...t.campaign?{campaign:t.campaign}:{},...t.availability?{availability:t.availability}:{},...t.retryCooldownMs===void 0?{}:{retryCooldownMs:t.retryCooldownMs},...t.completionCooldownMs===void 0?{}:{completionCooldownMs:t.completionCooldownMs}})}return y("quest",{protocol:_,key:a,describe:M,async evaluate(s){let d=t.settings.parse(s.settings),f=i?xe.parse(s.tracker):null,b=xt.get(t.trigger),w=f&&b?se(b,f.record.data):null;if(w)return L.parse({kind:"reject",reason:`The record's data does not match the data schema this quest was built with: ${w.path} ${w.reason}`});let S=f;if(s.performance){if(!t.performance)throw new Error("Quest has no performance evaluator");let v=ct.parse(s.performance),I=T(A(t.performance.metrics),z().int().safe().nonnegative()).parse(v.metrics),k=await t.performance.evaluate({settings:d,member:s.member,tracker:S,metrics:I,observedAt:v.observedAt});if(!k)throw new Error("Performance evaluator returned no decision");if(k.rewards!==void 0)throw new Error("A performance evaluator cannot select rewards. It gates the rewards content evaluation selected: return accept, review or reject with a reason only.");return qt(k),L.parse(k.kind==="accept"?{kind:"accept",rewards:v.rewards}:k.kind==="review"&&s.humanReview?{kind:"review",reason:k.reason,rewards:v.rewards}:{kind:"reject",reason:k.reason,...k.kind==="review"?{requestedReview:!0}:k.code===void 0?{}:{code:k.code}})}let h=t.evaluate?await t.evaluate({settings:d,member:s.member,input:s.input,tracker:S,eligibleAt:s.eligibleAt,calendar:s.calendar,now:s.now,review:s.review,trackers:ce(s.trackers),wallet:s.wallet,images:s.images,...s.telegram?{telegram:s.telegram}:{},...Object.fromEntries(n.map(v=>[v,s[v]]))}):x.accept();if(!h)throw new Error("Evaluator returned no decision");if(qt(h),h.kind==="review"&&!s.humanReview)return L.parse({kind:"reject",reason:h.reason,requestedReview:!0});(h.kind==="accept"||h.kind==="review")&&h.completionKey!==void 0&&o?.kind!=="keyed"&&s.diagnose?.({code:"completion-key-ignored",message:gr(o,h.completionKey)});let m={...s,settings:d,tracker:f};return L.parse(h.kind==="accept"||h.kind==="review"?{...h,rewards:h.rewards??s.rewards,...o?.kind==="keyed"||o?.kind==="progress"?{completionKey:o.kind==="progress"?o.distinct(m):h.completionKey??o.key(m)}:{}}:h)}})}}function gr(e,r){let t=`ignores completionKey ${JSON.stringify(r)}`;switch(e?.kind){case void 0:return`A content quest completes once per content item, under a key Relay sets, so it ${t}`;case"once":return`once() completes the quest once per member and ${t}: use keyed(...) to complete it once per key`;case"streak":return`streak(...) keys its own completions and ${t}`;case"progress":return`progress(...) keys each contribution with its distinct(...) and ${t}: derive the key in distinct(...)`}}var ia=$t(!1),ua=$t(!0);export{Gt as CapabilityError,ea as automatic,oa as automaticFulfillment,_r as badge,Vt as balanceAtLeast,ra as budget,zr as calendar,Ft as capabilityErrorCodes,Ut as completed,ta as content,Ie as cosmosDenomSchema,jt as cosmosNetworkSchema,Mr as count,R as customSource,x as decision,qr as defineBadge,Nt as defineCampaign,Wt as defineDashboard,xr as defineEngagementReward,Kt as defineGroup,Rr as defineLeaderboard,Cr as defineLedger,Qt as defineOffer,ia as defineQuest,ua as defineQuestType,jr as defineReferral,sa as defineTieredReward,Br as defineTracker,Dr as discord,Lr as earned,ca as evaluators,Xr as evidence,Ht as formatUnits,Hr as groupMembership,Zt as inGroup,Gr as instruction,Fr as invoked,Ue as isContractCall,Ve as isContractEvent,Oe as isEvmChainId,Ke as isNftCollection,Ze as isSolanaProgram,cr as keyed,Yr as manual,Dt as maxWalletEventLogs,Pt as maxWalletEventLookback,Ot as maxWalletTransactionLookback,It as maxWalletTransactions,ur as once,Tt as parseContractCall,Bt as parseContractEvent,Rt as parseContractFunction,Lt as parseNftCollection,_t as parseUnits,Kr as pointLedgers,Jr as points,ir as progress,Ar as questCompleted,Zr as received,$r as rolling,Ur as settings,Qr as spent,na as staffHandover,tr as streak,Wr as swapped,Pr as telegram,Or as tiktok,j as trackerDataSchema,xe as trackerTriggerContextSchema,aa as untracked,Nr as wallet,Tr as x,Ir as youtube,At as z};
1
+ import{$c as Ke,$d as C,$g as wr,A as se,Ae as or,Ba as Ur,Ca as Vr,Cd as F,Ce as sr,Dc as Pe,Dd as G,Dh as br,Ed as He,Fa as ke,Ga as we,Ha as ve,Hc as De,Hd as Je,Ia as be,Id as Xe,Ja as ye,Jd as Ye,Jg as x,Ka as Se,Kd as E,Ld as er,N as ce,Ne as _,Ng as fr,O as ie,Oc as Ie,P as ue,Pa as A,Pd as q,Pe as R,Qa as Ee,Qc as Oe,R as Pr,Ra as qe,S as de,Sa as Ce,Sd as Zr,Se as cr,U as Q,Yg as hr,Zd as y,Zg as pr,_c as Ne,_d as rr,_e as H,_g as kr,a as P,af as ir,ag as dr,bc as V,be as Wr,cc as Re,cd as Qe,dc as Z,dd as Ue,eb as xe,ec as Le,eg as lr,fb as Me,fg as mr,gg as J,ha as le,if as ur,jb as ze,jd as Ve,ka as me,kb as D,kh as Hr,la as Dr,ld as Ze,lh as Jr,ma as ge,md as We,nb as $e,nd as Fe,nh as Xr,ni as yr,oa as Ir,ob as U,od as Ge,pa as Or,pb as je,pd as _e,ph as vr,qa as fe,sb as Ae,se as Fr,ta as Nr,te as Gr,ua as he,ue as _r,va as Kr,vc as Te,ve as tr,w as te,wa as Qr,we as nr,wg as gr,x as ne,y as ae,ya as pe,yc as Be,yd as W,ye as ar,z as oe,zd as I}from"./chunks/Y4OAVXFR.js";import{Cb as z,Ec as j,Kb as Y,Pd as Br,fc as ee,ic as K,jc as re,va as N,wc as B}from"./chunks/EWU4OKSY.js";function Sr(e){if(!Number.isInteger(e)||e<0||e>255)throw new Error("Token decimals must be an integer from 0 to 255")}function Yr(e,t){Sr(t);let r=/^(\d+)(?:\.(\d+))?$/.exec(e.trim());if(!r)throw new Error(`Use a decimal amount such as "1.5", not "${e}"`);let[,n,a=""]=r,s=a.replace(/0+$/,"");if(s.length>t)throw new Error(`"${e}" has more than ${t} decimal places, which this token cannot hold`);return BigInt(n+s.padEnd(t,"0"))}function et(e,t){Sr(t);let r=typeof e=="bigint"?e:BigInt(e),n=r<0n?"-":"",a=(r<0n?-r:r).toString().padStart(t+1,"0"),s=a.slice(0,a.length-t),i=a.slice(a.length-t).replace(/0+$/,"");return n+s+(i?"."+i:"")}function qr(e,t={}){let{trigger:r,completion:n,requires:a,performance:s,retryCooldownMs:i,completionCooldownMs:u,authorBudgets:d=[]}=e,c=r.kind==="automatic"?r.tracker:void 0,g=c?.content===!0;if(s&&!g)throw new Error("Performance requires a content quest");if(!c&&d.length)throw new Error('A budget with scope "author" counts per tracker record author: use it only on a quest with a tracker trigger');if(g){if(n.kind!=="keyed"||n.across)throw new Error("Content quests complete once per content item");if(c.beneficiary!=="author"||c.on!=="new-record")throw new Error("A content quest pays each content item's author and fires on its first observation")}if(i!==void 0&&(r.kind!=="manual"||r.actor==="staff"))throw new Error("A retry cooldown applies only to quests members submit themselves");if(u!==void 0){if(r.kind!=="manual"||r.actor==="staff")throw new Error("A completion cooldown applies only to quests members submit themselves");if(n.kind==="once")throw new Error("A completion cooldown needs a quest members can complete more than once: this one completes once per member")}if(r.kind==="automatic"&&!c){if(!t.template&&a.length===0)throw new Error("Automatic quests need at least one prerequisite");if(n.kind!=="once")throw new Error("Prerequisite-only automatic quests complete once")}}var rt=["author"],tt=["author","messageAuthor"];function Cr(e){if(!Ae(e))return[];switch(e.kind){case"x-search":return xe;case"discord-messages":return rt;case"discord-reactions":return tt;case"custom":return["author",...e.accounts??[]]}}var Er=new Map;function nt(e){let t=e.kind==="discord-messages"&&e.text?"messages-text":e.kind,r=Er.get(t);return r||(r=A(t==="messages-text"?be:t==="discord-messages"?ve:ye),Er.set(t,r)),r}function xr(e){switch(e.kind){case"x-search":return;case"discord-messages":case"discord-reactions":return nt(e);case"custom":return e.data}}function $r(e,t){let r=typeof e=="object"&&e!==null&&"kind"in e&&e.kind==="tier"&&"reward"in e&&typeof e.reward=="object"&&e.reward!==null?e.reward:null;return r&&"badge"in r&&r.badge!==void 0?`Badge rewards can only be granted by quests or manually, not by ${t}`:r&&"group"in r&&r.group!==void 0?`Group membership rewards can only be granted by quests, not by ${t}`:null}function X(e,t,r,n){for(let[a,s]of t.entries()){let i=$r(s,n);i&&e.addIssue({code:"custom",message:i,path:[...r,a]})}}function At(e){return y("badge",x("Badge",vr,e))}function Rt(e){return y("ledger",x("Point ledger",br,e))}function Lt(e){let{target:t,ledger:r,...n}=e,a=lr.parse({...n,qualifiedBy:e.qualifiedBy.key,balance:C(r)}),s=B(j(e.metrics),J.shape.target);return{key:a.key,describe:()=>a,score(i){let u=mr.parse(i);return J.parse({target:t({metrics:s.parse(u.metrics)}),baseline:t({metrics:s.parse(u.baseline)})})}}}var ot=e=>{if("timeZone"in e)throw new Error("streak() no longer takes a timeZone. Set the project timezone with calendar.timeZone in relay.json or in Console settings.");return Te.strict().parse({kind:"streak",...e})},Tt=e=>Re.brand().parse({kind:"count",count:e}),Bt=(e,t={})=>Z.brand().parse({kind:"calendar",period:e,...t}),Pt=({days:e})=>Z.brand().parse({kind:"rolling",durationMs:e*864e5}),Dt=e=>({kind:"quest",quest:e}),st=fr.superRefine((e,t)=>{let r=$r(e.reward,"offers");r&&t.addIssue({code:"custom",message:r,path:["reward"]})});function It(e){return y("offer",x("Offer",st,e))}var ct=gr.superRefine((e,t)=>{for(let r of["inviter","invitee"])X(t,e.rewards[r],["rewards",r],"referral programs");for(let[r,n]of e.milestones.entries())X(t,n.rewards,["milestones",r,"rewards"],"referral programs")});function Ot(e){let{qualification:t,inviterGroup:r,milestones:n,bonuses:a,...s}=e,i=x("Referral",ct,{...s,qualification:t.kind==="quest"?{kind:"quest",quest:t.quest.key}:t,...r?{inviterGroup:P.parse(r.key)}:{},milestones:n?.map(({key:u,...d})=>({...d,id:q({key:u,...d})})),bonuses:a?.map(({key:u,ledger:d,quests:c,...g})=>({...g,id:q({key:u,...g}),balance:C(d),quests:c?.map(b=>b.key)}))});return y("referral",i)}function Nt(e={}){return{kind:"earned",...e}}var it=yr.superRefine((e,t)=>{for(let[r,n]of(e.settle?.prizes??[]).entries())X(t,n.rewards,["settle","prizes",r,"rewards"],"leaderboard prizes")});function Kt(e){let{ledger:t,group:r,score:n,settle:a,...s}=e,i=a?.pool,u=x("Leaderboard",it,{...s,...a?{settle:{...a,prizes:a.prizes??[],...i?{pool:{...i,...i.ledger===void 0?{}:{ledger:C(i.ledger)}}}:{}}}:{},balance:C(t),...r?{group:P.parse(r.key)}:{},score:n?.kind==="earned"?{...n,quests:n.quests?.map(d=>d.key)}:n});return y("leaderboard",u)}var Qt={provider:"x",search:e=>ze.parse({kind:"x-search",...e})};function L(e,t){let{data:r,content:n,...a}=t??{};if(n!==void 0){if(r!==void 0)throw new Error(`customSource("${e}") takes data or content, not both: a content source's records carry { body, metrics }`);if(!Mr(n.body))throw new Error(`customSource("${e}") needs a content body schema: customSource(namespace, { content: { body: z.object({ ... }), metrics: ["likes"] } })`);let s=[...n.metrics??[]];for(let i of s)Me.parse(i);return D.parse({kind:"custom",namespace:e,...a,data:A(K({body:n.body,metrics:re(Object.fromEntries(s.map(i=>[i,z().int().safe().nonnegative().optional()]))).optional()})),content:{metrics:s}})}if(!Mr(r))throw new Error(`customSource("${e}") needs a data schema: customSource(namespace, { data: z.object({ ... }) }) describes each record's data`);return D.parse({kind:"custom",namespace:e,...a,data:A(r)})}function Mr(e){return typeof e=="object"&&e!==null&&"_zod"in e}function Ut(e){return y("tracker",x("Tracker",je,e))}function ut(e={}){return ke.parse({kind:"discord-messages",...e.text?{text:!0}:{}})}function dt(){return we.parse({kind:"discord-reactions"})}var Vt={provider:"discord",grantRole:e=>Se.parse({kind:"integration",provider:"discord",action:"grant-role",roleId:e}),postMessage(e){return We.parse({provider:"discord",action:"post-message",...e})},messages:ut,reactions:dt,roles(e={}){return I.parse({provider:"discord",resource:"role",assignable:e.assignable??!1})},channels(e={}){return I.parse({provider:"discord",resource:"channel",types:e.types??["text","announcement"],...e.postable?{postable:!0}:{}})}},Zt={postMessage(e){return Ze.parse({provider:"telegram",action:"post-message",...e})},messages(){return L(ne,{identities:["member"],data:ie})},reactions(){return L(te,{identities:["member"],accounts:["messageAuthor"],data:ce})}},Wt={shorts(){return L(ae,{identities:["member"],content:{body:hr,metrics:pr}})}},Ft={videos(){return L(oe,{identities:["member"],content:{body:kr,metrics:wr}})}};function lt(e){let{chain:t,token:r}=e,n=r===void 0?null:r;if(n!==null&&typeof n!="string")throw new Error("wallet.balances() takes the token as a string");if(t==="solana"||t===Q){if(n!==null&&!ue.safeParse(n).success)throw new Error("wallet.balances() on Solana takes an SPL or Token-2022 mint address (base58)");return{chain:Q,token:n}}if(typeof t=="string"&&le(t)){if(n!==null&&!/^0x[0-9a-fA-F]{40}$/.test(n))throw new Error("wallet.balances() on an EVM chain takes an ERC-20 contract address: 0x and 40 hex digits");return{chain:t,token:n}}if(typeof t=="string"&&/^cosmos:[-_a-zA-Z0-9]{1,32}$/.test(t)){if(n===null||!de.safeParse(n).success)throw new Error("wallet.balances() on a Cosmos chain takes a bank denomination such as uatom");return{chain:t,token:n}}throw new Error('wallet.balances() reads "solana", an EVM chain such as "eip155:8453" or a Cosmos network such as "cosmos:cosmoshub-4"')}var Gt={balances(e){let t=lt(e),r=L(se,{identities:["wallet"],data:me});return D.parse({...r,balance:t})}},_t=()=>({provider:"domino",resource:"point-ledger"});function p(e,t){return t}var Ht={pointLedger(e){let t={...e,kind:"point-ledger",default:e.default?P.parse(e.default.key):""};return p("point-ledger",rr.prefault(t.default).meta(t))},datetime(e){let t={...e,kind:"datetime",default:F.parse(e.default)};return p("datetime",F.default(t.default).meta(t))},resource(e){let t={...e,source:I.parse(e.source),kind:"resource",default:G.parse(e.default??"")};return p("resource",G.default(t.default).meta(t))},quiz(e){let t=W.parse(e.default);return p("quiz",W.default(t).meta({...e,default:t,kind:"quiz"}))},text(e){let t={...e,kind:"text",minLength:e.minLength??1,maxLength:e.maxLength??2e3,multiline:e.multiline??!1};return p("text",N().min(t.minLength).max(t.maxLength).default(t.default).meta(t))},telegramChat(e){let t={...e,kind:"text",default:e.default??"",minLength:0,maxLength:64,multiline:!1,picker:"telegram-chat"};return p("text",N().max(t.maxLength).default(t.default).meta(t))},amount(e){if(!Je(e.default))throw new Error(`settings.amount() takes a base-unit integer string as its default, not "${e.default}"`);let t={...e,kind:"text",minLength:1,maxLength:100,multiline:!1,picker:"amount"};return p("text",E(t).default(t.default).meta(t))},chain(e){if(!Xe(e.default))throw new Error(`settings.chain() takes "solana" or an EVM chain ID such as "eip155:8453" as its default, not "${e.default}"`);let t={...e,kind:"text",minLength:1,maxLength:64,multiline:!1,picker:"chain"};return p("text",E(t).transform(r=>r).default(t.default).meta(t))},nft(e){if(!ge(e.default))throw new Error(`settings.nft() takes an NFT collection such as "eip155:1/erc721:0x\u2026" as its default, not "${e.default}"`);let t={...e,kind:"text",minLength:1,maxLength:200,multiline:!1,picker:"nft"};return p("text",E(t).transform(r=>r).default(t.default).meta(t))},contractCall(e){if(!fe(e.default))throw new Error(`settings.contractCall() takes a contract call such as "eip155:8453:0x\u2026 function stakedOf(address) view returns (uint256)" as its default, not "${e.default}"`);let t={...e,kind:"text",minLength:1,maxLength:400,multiline:!1,picker:"contract-call"};return p("text",E(t).transform(r=>r).default(t.default).meta(t))},contractEvent(e){if(!he(e.default))throw new Error(`settings.contractEvent() takes a contract event such as "eip155:1:0x\u2026 Transfer(address indexed from, address indexed to, uint256 value)" as its default, not "${e.default}"`);let t={...e,kind:"text",minLength:1,maxLength:1e3,multiline:!1,picker:"contract-event"};return p("text",E(t).transform(r=>r).default(t.default).meta(t))},solanaProgram(e){if(!pe(e.default))throw new Error(`settings.solanaProgram() takes a Solana program address such as "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4" as its default, not "${e.default}"`);let t={...e,kind:"text",minLength:32,maxLength:44,multiline:!1,picker:"solana-program"};return p("text",E(t).transform(r=>r).default(t.default).meta(t))},integer(e){return p("integer",z().int().min(e.min).max(e.max).default(e.default).meta({...e,kind:"integer"}))},boolean(e){return p("boolean",Y().default(e.default).meta({...e,kind:"boolean"}))},choice(e){return p("choice",j(e.options).default(e.default).meta({...e,kind:"choice"}))},object(e){return K(e).strict()}};function jr(e,t){let r=e.balanceChanges.find(n=>n.mint===t);return r?BigInt(r.delta):0n}function Xt(e,t){let r=jr(e,t);return r>0n?r.toString():"0"}function Yt(e,t){let r=jr(e,t);return r<0n?(-r).toString():"0"}function en(e,t={}){let r=e.balanceChanges.filter(a=>BigInt(a.delta)>0n),n=e.balanceChanges.filter(a=>BigInt(a.delta)<0n);return r.some(a=>(t.into===void 0||a.mint===t.into)&&n.some(s=>s.mint!==a.mint&&(t.from===void 0||s.mint===t.from)))}function rn(e,t){return e.programs.includes(t)}function tn(e,t){return e.instructions?.find(r=>r.name===t)?.args??null}var nn=e=>or(e.key,e.name),an=e=>sr(e.key,e.title),on=(e,t)=>tr.parse({kind:"points",balance:C(e),amount:t}),sn={text:(e={})=>({input:"text",constraints:Ge.parse(e)}),url:(e={})=>({input:"url",constraints:_e.parse(e)}),photo:()=>"photo",quiz:()=>"quiz"};function cn(e){if(e?.actor&&e.input!==void 0)throw new Error('manual() cannot combine actor "staff" with input: staff-captured evidence is not supported. Use manual({ actor: "staff" }) for a staff confirmation, or manual({ input }) for evidence the participant submits.');return typeof e?.input=="object"?{kind:"manual",...e.input}:{kind:"manual",input:e?.input??"none",...e?.actor?{actor:e.actor}:{}}}var Ar=new WeakMap,Rr=new WeakMap;function Lr(e,t){let{tracker:r,beneficiary:n="author",on:a,where:s,enrollment:i,since:u,historical:d,content:c}=e;if(!r?.source)throw new Error(t==="automatic"?"automatic() takes no argument, or { tracker } with a tracker handle from defineTracker":"content() takes { tracker } with a tracker handle from defineTracker");let{source:g}=r;if(!$e(g))throw new Error('Tracker triggers need attributable records: declare customSource(namespace, { identities: ["wallet"] }) or other identity kinds');if(c&&!U(g))throw new Error(`content() needs a tracker whose source has content: x.search(), or customSource(namespace, { content: { body, metrics } }). Tracker "${r.key}" has none; use automatic({ tracker }) instead.`);if(u==="enrollment"&&i!=="required")throw new Error(`${t}() counts from enrollment only on a quest that requires it: add enrollment: "required"`);let b=Cr(g);if(!b.includes(n))throw new Error(g.kind==="custom"?`Tracker "${r.key}" has no "${n}" account: declare it in customSource(namespace, { accounts: ["${n}"] })`:`Tracker "${r.key}" pays ${new Intl.ListFormat("en",{type:"disjunction"}).format(b.map(w=>`"${w}"`))}, not "${n}"`);let T=De.parse({tracker:r.key,source:g.kind,on:c?"new-record":a??Be(g.kind),...s?{where:s}:{},beneficiary:n,...i==="required"?{enrollment:i}:{},...u&&u!=="activation"?{since:u}:{},...d&&d!==(c?"claim":"staff")?{historical:d}:{},...c?{content:c}:{}}),o=xr(g),l=o?Ce(o,T.where):null;if(l)throw new Error(l);let h={kind:"automatic",tracker:T};o&&Ar.set(h,o);let S=U(g);return S&&Rr.set(h,S.metrics),h}function un(e){return e?Lr(e,"automatic"):{kind:"automatic"}}function dn(e){if(e&&typeof e=="object"&&"source"in e&&"key"in e&&!("tracker"in e))throw new Error("content() takes { tracker }: write content({ tracker: posts }) instead of content(posts)");return Lr({...e,content:!0},"content")}function mt(e){let{key:t,cost:r,...n}=e,a={...n,id:q(e),cost:typeof r=="number"?r:{balance:C(r.ledger)}};return n.scope==="author"?Ke.parse(a):Ne.parse(a)}var ln=mt,gt=(e=[])=>e.filter(t=>t.scope==="author"),ft=(e,t={})=>({kind:"keyed",key:e,...t.across?{across:t.across}:{}}),ht=e=>{let{distinct:t,...r}=e;return{...Le.parse({kind:"progress",window:{kind:"lifetime"},...r}),distinct:t}},mn=()=>({kind:"untracked"}),gn=()=>({kind:"staff-handover"}),fn=()=>({kind:"automatic"});function hn(e){let{key:t,tiers:r,...n}=e,a=q(e),s=nr.parse({id:a,...n,tiers:r.map(({key:i,...u})=>({...u,id:q({key:i,...u})}))});return y("tiered-reward",{key:s.id,tier:i=>ar.parse({kind:"tier",reward:s,tier:i})})}var pt=()=>({kind:"once"});function kt(e={}){return{kind:"accept",...e}}function wt(e){return{kind:"review",...e}}var M={accept:kt,defer:e=>({kind:"defer",...e}),progress:e=>({kind:"progress",...e}),reject:e=>({kind:"reject",...e}),review:wt};function zr(e){let t=e.kind==="reject"&&e.code!==void 0?Oe(e.code):null;if(t)throw new Error(t)}var pn={quiz(e,t={}){let r=ur.parse(e),n=Object.keys(r),a=z().int().min(1).max(n.length).parse(t.minimumCorrect??n.length);return async({input:s})=>{let i=Object.keys(s.answers).length===n.length&&n.every(d=>Object.hasOwn(s.answers,d)),u=n.filter(d=>s.answers[d]===r[d]).length;return i&&u>=a?M.accept():M.reject({reason:"Review your answers and try again."})}},photo(e){return async t=>{let r=e(t),n=await t.review.photo({image:t.input.photo,criteria:r.criteria});return n.kind==="unclear"?r.unclear==="human-review"?M.review({reason:n.reason}):M.reject({reason:n.reason}):n.kind==="pass"?M.accept():M.reject({reason:n.reason})}}},vt={once:pt,keyed:ft,streak:ot,progress:ht};function Tr(e){return function(r){let n=q(r),a=[...new Set((r.integrations??[]).map(o=>Ue.parse(o.provider)))],s=a.flatMap(o=>{let l=Qe.safeParse(o);return l.success?[l.data]:[]}),i=r.trigger.kind==="automatic"&&r.trigger.tracker?.content===!0,u=r.trigger.kind==="automatic"&&r.trigger.tracker!==void 0,d=r.completion,c=typeof d=="function"?d(vt):d;if(i&&c!==void 0)throw new Error("A content quest completes once per content item: remove its completion");if(!i&&c===void 0)throw new Error("A quest needs a completion, such as once(), keyed(...), streak(...) or progress(...)");let g=gt(r.budgets);if(qr({trigger:r.trigger,completion:c??{kind:"keyed"},requires:r.requires??[],authorBudgets:g,performance:r.performance?V.parse({metrics:r.performance.metrics,maxAgeMs:r.performance.maxAgeMs}):void 0,...r.retryCooldownMs===void 0?{}:{retryCooldownMs:r.retryCooldownMs},...r.completionCooldownMs===void 0?{}:{completionCooldownMs:r.completionCooldownMs}},{template:e}),r.retryCooldownMs!==void 0&&!_.safeParse(r.retryCooldownMs).success)throw new Error("retryCooldownMs must be whole milliseconds from 1000 (one second) to 604800000 (seven days)");if(r.completionCooldownMs!==void 0&&!_.safeParse(r.completionCooldownMs).success)throw new Error("completionCooldownMs must be whole milliseconds from 1000 (one second) to 604800000 (seven days)");if(r.performance){let o=Rr.get(r.trigger)??[],l=r.performance.metrics.filter(h=>!o.includes(h));if(l.length)throw new Error(`The tracker's source does not measure ${l.join(", ")}`)}if(r.trigger.kind==="manual"&&r.trigger.input!=="none"&&!r.evaluate)throw new Error("Evidence quests require an evaluator");let b=Object.fromEntries(Object.entries(r.settings.shape).map(([o,l])=>{let h=He.safeParse(l.meta());if(!h.success)throw new Error(`Setting "${o}" is not a quest setting: build it with a settings builder, such as settings.integer({ label, default, min, max })`);return[o,h.data]}));for(let o of Pe(r.trigger.kind==="automatic"?r.trigger.tracker?.where:void 0))if(!Ye(b[o]))throw new Error(`The tracker filter compares with setting "${o}", which is not an integer or amount setting`);function T(o){let l=r.settings.parse(o),h=er(b,l),S=cr.parse(typeof r.rewards=="function"?r.rewards({settings:l}):r.rewards),w=ee(Fe).max(3,"A quest posts at most three announcements").parse((typeof r.announcements=="function"?r.announcements({settings:l}):r.announcements)??[]),$=r.trigger.kind==="automatic"&&r.trigger.tracker!==void 0;for(let m of w){let v=Ve(m.text),O="segments"in v&&v.segments.some(k=>k.kind==="placeholder"&&k.name==="author");if(!$&&O)throw new Error("An announcement names {author} only on a quest with an automatic tracker trigger");if(!$&&m.replyToTriggeringMessage)throw new Error("An announcement replies to the triggering message only on a quest with an automatic tracker trigger")}let f=[...S.flatMap(m=>m.kind==="integration"?[m.provider]:[]),...w.flatMap(m=>m.provider==="discord"?["discord"]:[]),...Object.values(b).flatMap(m=>m.kind==="resource"&&m.source.provider!=="domino"?[m.source.provider]:[])];for(let m of f)if(!s.includes(m))throw new Error(`Declare the ${m} integration on this quest`);return ir.parse({quest:n,evaluatorProtocol:H,title:typeof r.title=="function"?r.title({settings:l}):r.title,presentation:r.presentation?.({settings:l})??{},fields:b,values:h,rewards:S,...w.length?{announcements:w}:{},humanReview:r.review?.({settings:l})?.enabled??!0,trigger:r.trigger,...r.performance?{performance:V.parse({metrics:r.performance.metrics,maxAgeMs:r.performance.maxAgeMs})}:{},integrations:s,...a.length>s.length?{integrationModules:a}:{},completion:c?c.kind==="progress"?{kind:c.kind,goal:c.goal,window:c.window,repeat:c.repeat}:c.kind==="streak"?c:c.kind==="keyed"&&c.across?{kind:c.kind,across:c.across}:{kind:c.kind}:{kind:"keyed"},visibility:r.visibility??"visible",profile:r.profile??{visible:!1},budgets:(r.budgets??[]).filter(m=>m.scope!=="author"),...g.length?{authorBudgets:g}:{},requires:r.requires??[],...r.campaign?{campaign:r.campaign}:{},...r.availability?{availability:r.availability}:{},...r.retryCooldownMs===void 0?{}:{retryCooldownMs:r.retryCooldownMs},...r.completionCooldownMs===void 0?{}:{completionCooldownMs:r.completionCooldownMs}})}return y("quest",{protocol:H,key:n,describe:T,async evaluate(o){let l=r.settings.parse(o.settings),h=u?Ie.parse(o.tracker):null,S=Ar.get(r.trigger),w=h&&S?Ee(S,h.record.data):null;if(w)return R.parse({kind:"reject",reason:`The record's data does not match the data schema this quest was built with: ${w.path} ${w.reason}`});let $=h;if(o.performance){if(!r.performance)throw new Error("Quest has no performance evaluator");let v=dr.parse(o.performance),O=B(j(r.performance.metrics),z().int().safe().nonnegative()).parse(v.metrics),k=await r.performance.evaluate({settings:l,member:o.member,tracker:$,metrics:O,observedAt:v.observedAt});if(!k)throw new Error("Performance evaluator returned no decision");if(k.rewards!==void 0)throw new Error("A performance evaluator cannot select rewards. It gates the rewards content evaluation selected: return accept, review or reject with a reason only.");return zr(k),R.parse(k.kind==="accept"?{kind:"accept",rewards:v.rewards}:k.kind==="review"&&o.humanReview?{kind:"review",reason:k.reason,rewards:v.rewards}:{kind:"reject",reason:k.reason,...k.kind==="review"?{requestedReview:!0}:k.code===void 0?{}:{code:k.code}})}let f=r.evaluate?await r.evaluate({settings:l,member:o.member,input:o.input,tracker:$,eligibleAt:o.eligibleAt,calendar:o.calendar,now:o.now,review:o.review,trackers:qe(o.trackers),wallet:o.wallet,images:o.images,...o.telegram?{telegram:o.telegram}:{},...Object.fromEntries(s.map(v=>[v,o[v]]))}):M.accept();if(!f)throw new Error("Evaluator returned no decision");if(zr(f),f.kind==="review"&&!o.humanReview)return R.parse({kind:"reject",reason:f.reason,requestedReview:!0});(f.kind==="accept"||f.kind==="review")&&f.completionKey!==void 0&&c?.kind!=="keyed"&&o.diagnose?.({code:"completion-key-ignored",message:bt(c,f.completionKey)});let m={...o,settings:l,tracker:h};return R.parse(f.kind==="accept"||f.kind==="review"?{...f,rewards:f.rewards??o.rewards,...c?.kind==="keyed"||c?.kind==="progress"?{completionKey:c.kind==="progress"?c.distinct(m):f.completionKey??c.key(m)}:{}}:f)}})}}function bt(e,t){let r=`ignores completionKey ${JSON.stringify(t)}`;switch(e?.kind){case void 0:return`A content quest completes once per content item, under a key Relay sets, so it ${r}`;case"once":return`once() completes the quest once per member and ${r}: use keyed(...) to complete it once per key`;case"streak":return`streak(...) keys its own completions and ${r}`;case"progress":return`progress(...) keys each contribution with its distinct(...) and ${r}: derive the key in distinct(...)`}}var kn=Tr(!1),wn=Tr(!0);export{Xr as CapabilityError,un as automatic,fn as automaticFulfillment,nn as badge,Gr as balanceAtLeast,ln as budget,Bt as calendar,Jr as capabilityErrorCodes,Fr as completed,dn as content,de as cosmosDenomSchema,Pr as cosmosNetworkSchema,Tt as count,L as customSource,M as decision,At as defineBadge,Zr as defineCampaign,Hr as defineDashboard,Lt as defineEngagementReward,Wr as defineGroup,Kt as defineLeaderboard,Rt as defineLedger,It as defineOffer,kn as defineQuest,wn as defineQuestType,Ot as defineReferral,hn as defineTieredReward,Ut as defineTracker,Vt as discord,Nt as earned,pn as evaluators,sn as evidence,et as formatUnits,an as groupMembership,_r as inGroup,tn as instruction,rn as invoked,fe as isContractCall,he as isContractEvent,le as isEvmChainId,ge as isNftCollection,pe as isSolanaProgram,ft as keyed,cn as manual,Kr as maxWalletEventLogs,Qr as maxWalletEventLookback,Vr as maxWalletTransactionLookback,Ur as maxWalletTransactions,pt as once,Or as parseContractCall,Nr as parseContractEvent,Ir as parseContractFunction,Dr as parseNftCollection,Yr as parseUnits,_t as pointLedgers,on as points,ht as progress,Dt as questCompleted,Xt as received,Pt as rolling,Ht as settings,Yt as spent,gn as staffHandover,ot as streak,en as swapped,Zt as telegram,Ft as tiktok,A as trackerDataSchema,Ie as trackerTriggerContextSchema,mn as untracked,Gt as wallet,Qt as x,Wt as youtube,Br as z};