@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.
- package/CHANGELOG.md +156 -8
- package/README.md +3 -2
- package/dist/{schema-CZ6Rj0ZF.d.ts → accounts-CCqCKCVx.d.ts} +3127 -1764
- package/dist/action-9Xl0StBg.d.ts +33 -0
- package/dist/{integrations-B3y36OaB.d.ts → analytics-BwAKLi7O.d.ts} +347 -57
- package/dist/{attempt-captures-DYnJVkfg.d.ts → attempt-captures-Cm-5G0PC.d.ts} +1 -1
- package/dist/authoring.d.ts +130 -42
- package/dist/authoring.js +112 -37
- package/dist/{automatic-outcomes-If88LR9f.d.ts → automatic-outcomes-pAsOyIVp.d.ts} +5 -1
- package/dist/avatar.d.ts +1 -1
- package/dist/browser.d.ts +15 -11
- package/dist/browser.js +15 -11
- package/dist/{announcements-CHx3-HBw.d.ts → capability-error-DFMwSuSf.d.ts} +161 -4
- package/dist/{pages-K7-KjSXw.d.ts → catalog--ZIlskAo.d.ts} +39 -561
- package/dist/{chunk-DYXDZFKA.js → chunk-3KLC4AMA.js} +37 -11
- package/dist/{chunk-XBV2CK2H.js → chunk-3PYYGFSB.js} +14 -2
- package/dist/{chunk-RHBS5FJL.js → chunk-5TEYFX6X.js} +2 -2
- package/dist/chunk-6WCIWXUV.js +31 -0
- package/dist/chunk-CICDIBOF.js +373 -0
- package/dist/{chunk-MHPKEVEW.js → chunk-CZFXGGEK.js} +5 -0
- package/dist/chunk-D26YNACF.js +320 -0
- package/dist/{chunk-5I54XBK2.js → chunk-E6IKQHTX.js} +2 -2
- package/dist/chunk-FWLQ5XCS.js +21 -0
- package/dist/{chunk-SKGTNTLF.js → chunk-GKIFABGN.js} +150 -61
- package/dist/chunk-GTDW453U.js +522 -0
- package/dist/{chunk-VURRFVNP.js → chunk-HTZHBTIL.js} +69 -27
- package/dist/chunk-K2KS3JLY.js +188 -0
- package/dist/{chunk-ZDJLPN4L.js → chunk-MK425RXJ.js} +3143 -3209
- package/dist/{chunk-L77O64I4.js → chunk-QYPMPWVX.js} +1 -1
- package/dist/chunk-UAKYDVT3.js +565 -0
- package/dist/{chunk-DHXDBAJF.js → chunk-UPQPUJOU.js} +36 -123
- package/dist/{chunk-24I4R732.js → chunk-UW5232GG.js} +34 -19
- package/dist/chunk-WSBYWVTZ.js +717 -0
- package/dist/{chunk-PPB7HALD.js → chunk-XJFYAXET.js} +9 -8
- package/dist/{chunk-7A4J67ZL.js → chunk-XNKSSE32.js} +1 -1
- package/dist/{chunk-QEAS4ZGS.js → chunk-Y322OTCH.js} +1 -1
- package/dist/{client-C51w7fMb.d.ts → client-B-hbHX30.d.ts} +109 -40
- package/dist/{deployments-kWoHFaqj.d.ts → deployments-M4OHn7G3.d.ts} +407 -18
- package/dist/identity-integration-3mX6b5iH.d.ts +1241 -0
- package/dist/index.d.ts +13 -11
- package/dist/index.js +14 -11
- package/dist/internal.d.ts +14 -12
- package/dist/internal.js +26 -14
- package/dist/{offers-BoV4ryUc.d.ts → offers-DhAtss4_.d.ts} +21 -4
- package/dist/pages-B8q8Y_dQ.d.ts +715 -0
- package/dist/{participant-activity-DHL8QYks.d.ts → participant-activity-D-Drp24G.d.ts} +16 -3
- package/dist/portal-proxy.d.ts +59 -2
- package/dist/portal-proxy.js +109 -23
- package/dist/react/index.d.ts +206 -26
- package/dist/react/index.js +153 -25
- package/dist/{action-DBzILFx9.d.ts → request-error-D_dUPLwo.d.ts} +1 -31
- package/dist/runtime/authoring.js +1 -1
- package/dist/runtime/chunks/Y4OAVXFR.js +1 -0
- package/dist/runtime/manifest.json +3 -3
- package/dist/runtime/schema.js +1 -1
- package/dist/schema.d.ts +154 -30
- package/dist/schema.js +126 -75
- package/dist/server/index.d.ts +14 -12
- package/dist/server/index.js +2137 -1633
- package/dist/sign-in-providers-BkjcDsFF.d.ts +39 -0
- package/dist/submission-input-DHGKhXfp.d.ts +342 -0
- package/dist/{telegram-browser-BUceZIGZ.d.ts → telegram-browser-BCE7zdOb.d.ts} +46 -6
- package/dist/telegram.d.ts +64 -0
- package/dist/telegram.js +23 -0
- package/dist/testing.d.ts +112 -15
- package/dist/testing.js +321 -16
- package/dist/tracker-data-Hb1uQnk5.d.ts +1855 -0
- package/dist/{transport-BrX9pIGN.d.ts → transport-DkhX2Cbs.d.ts} +5764 -2217
- package/dist/{wallet-CIqFoxdm.d.ts → wallet-DTO7SXj7.d.ts} +20 -7
- package/package.json +5 -1
- package/dist/accounts-DoabriBX.d.ts +0 -306
- package/dist/capability-error-DufwG3G0.d.ts +0 -159
- package/dist/chunk-3Y3L2F54.js +0 -982
- package/dist/chunk-EN3M5Z4J.js +0 -13
- package/dist/chunk-QNUHWK7R.js +0 -602
- package/dist/chunk-SE4PFJPT.js +0 -247
- package/dist/groups-CqcA2Ycs.d.ts +0 -2827
- package/dist/runtime/chunks/5QVFB4TU.js +0 -1
- package/dist/submission-input-C54Q8yAD.d.ts +0 -146
- package/dist/x-D1PGi8Sq.d.ts +0 -331
package/dist/react/index.js
CHANGED
|
@@ -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-
|
|
13
|
-
import "../chunk-
|
|
14
|
+
} from "../chunk-FWLQ5XCS.js";
|
|
15
|
+
import "../chunk-GKIFABGN.js";
|
|
14
16
|
import {
|
|
15
17
|
createRelayAction
|
|
16
|
-
} from "../chunk-
|
|
17
|
-
import "../chunk-
|
|
18
|
-
import "../chunk-
|
|
19
|
-
import "../chunk-
|
|
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-
|
|
22
|
-
import "../chunk-EN3M5Z4J.js";
|
|
25
|
+
import "../chunk-3PYYGFSB.js";
|
|
23
26
|
import {
|
|
24
27
|
sessionMember
|
|
25
|
-
} from "../chunk-
|
|
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-
|
|
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.
|
|
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
|
-
/**
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
3366
|
+
const redeem = useCallback10(
|
|
3241
3367
|
(offer) => mutateAsync(offer).catch(() => null),
|
|
3242
3368
|
[mutateAsync]
|
|
3243
3369
|
);
|
|
3244
|
-
return
|
|
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
|
-
|
|
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};
|