@domino-sdk/relay 1.70.0 → 1.72.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 +28 -0
- package/dist/{accounts-B49TGZLk.d.ts → accounts-COLmXRbW.d.ts} +144 -11
- package/dist/{attempt-captures-Dn-oGE1o.d.ts → attempt-captures-CVl161qB.d.ts} +3 -2
- package/dist/authoring.d.ts +68 -25
- package/dist/authoring.js +12 -8
- package/dist/{automatic-outcomes-DeRyox-X.d.ts → automatic-outcomes-5l68PGr1.d.ts} +2 -2
- package/dist/browser.d.ts +9 -9
- package/dist/browser.js +11 -9
- package/dist/{catalog-CR_2iacf.d.ts → catalog-BR3g-1H9.d.ts} +41 -2
- package/dist/{chunk-NOQSKRSS.js → chunk-2UELTHW6.js} +12 -4
- package/dist/{chunk-SELJYCYY.js → chunk-3KKRXN5E.js} +1 -1
- package/dist/{chunk-4VDRNYUG.js → chunk-74SMLZZ5.js} +710 -677
- package/dist/{chunk-4BBDHTBF.js → chunk-ASBDB436.js} +1 -1
- package/dist/{chunk-3DUNFRKJ.js → chunk-BXUF3CRL.js} +32 -6
- package/dist/{chunk-BJ2W5ZVQ.js → chunk-CVJTIVAP.js} +1 -1
- package/dist/{chunk-FHOKCBTJ.js → chunk-ETGKC2SB.js} +1 -1
- package/dist/{chunk-XD6EUA27.js → chunk-FGZGL5PG.js} +1 -1
- package/dist/{chunk-OKKZPDCQ.js → chunk-GHBYWDEZ.js} +8 -1
- package/dist/{chunk-SDWG7CWQ.js → chunk-HN7DE2UN.js} +2 -2
- package/dist/{chunk-25WA4XYZ.js → chunk-I7XIBXT2.js} +74 -5
- package/dist/{chunk-UKUIE2ND.js → chunk-KIRXE37T.js} +6 -6
- package/dist/{chunk-VAGGGB6B.js → chunk-MDSSIOBC.js} +58 -1
- package/dist/{chunk-LZXDYSUH.js → chunk-PYZSCFMJ.js} +4 -0
- package/dist/{chunk-XZCTCSDG.js → chunk-QG6XVOOO.js} +153 -4
- package/dist/{chunk-2GVGZ7AN.js → chunk-TW4RABVS.js} +1 -1
- package/dist/{chunk-RYUM6X2K.js → chunk-UEVZ3TST.js} +29 -2
- package/dist/{chunk-HICAGUT5.js → chunk-VFHLMNYV.js} +1 -1
- package/dist/{chunk-RSZAYW3T.js → chunk-W6DBNBMT.js} +2 -2
- package/dist/{client-gJEheT2C.d.ts → client-B__hMWtK.d.ts} +104 -7
- package/dist/{dashboards-DZaB94sz.d.ts → dashboards-DXpjHnq-.d.ts} +3 -3
- package/dist/{deployments-QVGxC-fT.d.ts → deployments-CT2kQloT.d.ts} +199 -3
- package/dist/{identity-integration-BAJdzbdl.d.ts → identity-integration-ClX4oUAu.d.ts} +4 -4
- package/dist/index.d.ts +10 -10
- package/dist/index.js +7 -7
- package/dist/internal.d.ts +44 -26
- package/dist/internal.js +26 -50
- package/dist/{limits-UawUbr0S.d.ts → limits-B7wbnWhd.d.ts} +1 -1
- package/dist/{offers-0hqbnogq.d.ts → offers-D4pyeY9b.d.ts} +2 -2
- package/dist/portal-proxy.d.ts +2 -2
- package/dist/portal-proxy.js +10 -10
- package/dist/react/index.d.ts +31 -12
- package/dist/react/index.js +115 -41
- package/dist/{reward-deliveries-ARvt1UXb.d.ts → reward-deliveries-HGpj1VFz.d.ts} +1 -1
- package/dist/runtime/authoring.js +1 -1
- package/dist/runtime/chunks/A7G5P76B.js +1 -0
- package/dist/runtime/manifest.json +3 -3
- package/dist/runtime/schema.js +1 -1
- package/dist/schema.d.ts +40 -16
- package/dist/schema.js +7 -7
- package/dist/server/index.d.ts +12 -12
- package/dist/server/index.js +956 -576
- package/dist/{sign-in-providers-DCiufSGG.d.ts → sign-in-providers-lbOXCF8N.d.ts} +2 -2
- package/dist/solana.d.ts +12 -12
- package/dist/solana.js +8 -8
- package/dist/{telegram-browser-yx9WuNLX.d.ts → station-check-in-qBiaftfE.d.ts} +89 -7
- package/dist/{submission-input-C0DLv5Dj.d.ts → submission-input-U4aIkJuT.d.ts} +2 -2
- package/dist/telegram.d.ts +7 -7
- package/dist/testing.d.ts +15 -11
- package/dist/testing.js +23 -12
- package/dist/{tracker-data-CUopgomU.d.ts → tracker-data-2BYXZjsN.d.ts} +3 -3
- package/dist/{transport-e0uY1R7z.d.ts → transport-DcRXDZ1j.d.ts} +1838 -19
- package/dist/{wallet-CJTULM0Q.d.ts → wallet-BqswMAqZ.d.ts} +2 -2
- package/dist/{wallet-browser-DScvrvIj.d.ts → wallet-browser-B5r7u3xB.d.ts} +1 -1
- package/package.json +1 -1
- package/dist/runtime/chunks/447P2VLY.js +0 -1
package/dist/react/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
+
captureStationCheckIn,
|
|
3
|
+
checkInStation,
|
|
2
4
|
cosmosChainList,
|
|
3
5
|
cosmosChainsError,
|
|
4
6
|
createBrowserRelayClient,
|
|
@@ -6,26 +8,32 @@ import {
|
|
|
6
8
|
discoverEvmWallets,
|
|
7
9
|
discoverSignInWallets,
|
|
8
10
|
discoverSolanaWallets,
|
|
11
|
+
isRefusal,
|
|
12
|
+
readSessionItem,
|
|
13
|
+
readSessionJson,
|
|
9
14
|
readSignInMethods,
|
|
10
|
-
|
|
11
|
-
|
|
15
|
+
sendStationCheckIn,
|
|
16
|
+
signInOptionsFrom,
|
|
17
|
+
stationCheckInRetryable,
|
|
18
|
+
writeSessionItem
|
|
19
|
+
} from "../chunk-QG6XVOOO.js";
|
|
12
20
|
import {
|
|
13
21
|
telegramMiniAppInitData
|
|
14
22
|
} from "../chunk-FWLQ5XCS.js";
|
|
15
|
-
import "../chunk-
|
|
23
|
+
import "../chunk-BXUF3CRL.js";
|
|
16
24
|
import {
|
|
17
25
|
createRelayAction
|
|
18
26
|
} from "../chunk-5RLIPTL7.js";
|
|
19
27
|
import "../chunk-LDO5GP7G.js";
|
|
20
|
-
import "../chunk-
|
|
21
|
-
import "../chunk-
|
|
22
|
-
import "../chunk-
|
|
23
|
-
import "../chunk-
|
|
28
|
+
import "../chunk-MDSSIOBC.js";
|
|
29
|
+
import "../chunk-ASBDB436.js";
|
|
30
|
+
import "../chunk-ETGKC2SB.js";
|
|
31
|
+
import "../chunk-3KKRXN5E.js";
|
|
24
32
|
import {
|
|
25
33
|
sessionMember
|
|
26
|
-
} from "../chunk-
|
|
27
|
-
import "../chunk-
|
|
28
|
-
import "../chunk-
|
|
34
|
+
} from "../chunk-TW4RABVS.js";
|
|
35
|
+
import "../chunk-FGZGL5PG.js";
|
|
36
|
+
import "../chunk-74SMLZZ5.js";
|
|
29
37
|
import {
|
|
30
38
|
RelayError,
|
|
31
39
|
RelayErrorCode,
|
|
@@ -1065,24 +1073,13 @@ function isVisible() {
|
|
|
1065
1073
|
}
|
|
1066
1074
|
var WALLET_SIGN_IN_KEY = "domino:wallet-sign-in";
|
|
1067
1075
|
function readWalletSignIn() {
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
return typeof value?.session === "string" && typeof value.address === "string" && typeof value.chain === "string" ? value : null;
|
|
1073
|
-
} catch {
|
|
1074
|
-
return null;
|
|
1075
|
-
}
|
|
1076
|
+
return readSessionJson(
|
|
1077
|
+
WALLET_SIGN_IN_KEY,
|
|
1078
|
+
(value) => typeof value?.session === "string" && typeof value.address === "string" && typeof value.chain === "string"
|
|
1079
|
+
);
|
|
1076
1080
|
}
|
|
1077
1081
|
function writeWalletSignIn(value) {
|
|
1078
|
-
|
|
1079
|
-
if (value) {
|
|
1080
|
-
window.sessionStorage.setItem(WALLET_SIGN_IN_KEY, JSON.stringify(value));
|
|
1081
|
-
} else {
|
|
1082
|
-
window.sessionStorage.removeItem(WALLET_SIGN_IN_KEY);
|
|
1083
|
-
}
|
|
1084
|
-
} catch {
|
|
1085
|
-
}
|
|
1082
|
+
writeSessionItem(WALLET_SIGN_IN_KEY, value && JSON.stringify(value));
|
|
1086
1083
|
}
|
|
1087
1084
|
function reportingSigner(signer, signed) {
|
|
1088
1085
|
return {
|
|
@@ -3207,20 +3204,13 @@ function captureReferralCode(param = "ref") {
|
|
|
3207
3204
|
return null;
|
|
3208
3205
|
}
|
|
3209
3206
|
const code = new URL(window.location.href).searchParams.get(param);
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
window.sessionStorage.setItem(PENDING, code);
|
|
3213
|
-
}
|
|
3214
|
-
return window.sessionStorage.getItem(PENDING);
|
|
3215
|
-
} catch {
|
|
3216
|
-
return code && CODE.test(code) ? code : null;
|
|
3207
|
+
if (code && CODE.test(code)) {
|
|
3208
|
+
writeSessionItem(PENDING, code);
|
|
3217
3209
|
}
|
|
3210
|
+
return code && CODE.test(code) ? code : readSessionItem(PENDING);
|
|
3218
3211
|
}
|
|
3219
3212
|
function forgetReferralCode() {
|
|
3220
|
-
|
|
3221
|
-
window.sessionStorage.removeItem(PENDING);
|
|
3222
|
-
} catch {
|
|
3223
|
-
}
|
|
3213
|
+
writeSessionItem(PENDING, null);
|
|
3224
3214
|
}
|
|
3225
3215
|
function useInvitation(param = "ref") {
|
|
3226
3216
|
const relay = useRelay();
|
|
@@ -3275,7 +3265,7 @@ function useInvitation(param = "ref") {
|
|
|
3275
3265
|
return;
|
|
3276
3266
|
}
|
|
3277
3267
|
const cause = owner.action.error ?? caught;
|
|
3278
|
-
const refused =
|
|
3268
|
+
const refused = isRefusal(cause) && cause.status !== 429 || isRelayError(cause) && cause.code === RelayErrorCode.InvalidInput;
|
|
3279
3269
|
if (refused) {
|
|
3280
3270
|
forgetReferralCode();
|
|
3281
3271
|
}
|
|
@@ -3370,8 +3360,91 @@ function useQuestOutcomes(query = {}) {
|
|
|
3370
3360
|
);
|
|
3371
3361
|
}
|
|
3372
3362
|
|
|
3363
|
+
// src/react/stations.ts
|
|
3364
|
+
import { useCallback as useCallback10, useEffect as useEffect8, useMemo as useMemo12, useRef as useRef8, useState as useState9 } from "react";
|
|
3365
|
+
function useStationCheckIn(options = {}) {
|
|
3366
|
+
const relay = useRelay();
|
|
3367
|
+
const invalidate = useInvalidate();
|
|
3368
|
+
const signed = useSession();
|
|
3369
|
+
const { member } = signed;
|
|
3370
|
+
const session = signed.data?.id;
|
|
3371
|
+
const [pending] = useState9(
|
|
3372
|
+
captureStationCheckIn
|
|
3373
|
+
);
|
|
3374
|
+
const [settled, setSettled] = useState9(null);
|
|
3375
|
+
const [finished, setFinished] = useState9(false);
|
|
3376
|
+
const labels = useRef8(options);
|
|
3377
|
+
labels.current = options;
|
|
3378
|
+
const started = useRef8(null);
|
|
3379
|
+
const owner = `${member}:${session}`;
|
|
3380
|
+
const send = useCallback10(async () => {
|
|
3381
|
+
if (!pending || !member) {
|
|
3382
|
+
return;
|
|
3383
|
+
}
|
|
3384
|
+
const current = `${member}:${session}`;
|
|
3385
|
+
started.current = current;
|
|
3386
|
+
setSettled({
|
|
3387
|
+
owner: current,
|
|
3388
|
+
state: {
|
|
3389
|
+
status: "checking",
|
|
3390
|
+
quest: pending.quest,
|
|
3391
|
+
station: checkInStation(pending, labels.current)
|
|
3392
|
+
}
|
|
3393
|
+
});
|
|
3394
|
+
const state = await sendStationCheckIn(relay, pending, {
|
|
3395
|
+
...labels.current,
|
|
3396
|
+
session
|
|
3397
|
+
});
|
|
3398
|
+
if (started.current !== current) {
|
|
3399
|
+
return;
|
|
3400
|
+
}
|
|
3401
|
+
setSettled({ owner: current, state });
|
|
3402
|
+
if (state.status === "checked-in" || state.status === "refused") {
|
|
3403
|
+
setFinished(!stationCheckInRetryable(state));
|
|
3404
|
+
}
|
|
3405
|
+
if (state.status === "checked-in") {
|
|
3406
|
+
void invalidate([relayKeys.experience]);
|
|
3407
|
+
}
|
|
3408
|
+
}, [relay, pending, member, session, invalidate]);
|
|
3409
|
+
useEffect8(() => {
|
|
3410
|
+
if (pending && member && !finished && started.current !== `${member}:${session}`) {
|
|
3411
|
+
void send();
|
|
3412
|
+
}
|
|
3413
|
+
}, [pending, member, session, finished, send]);
|
|
3414
|
+
const retry = useCallback10(async () => {
|
|
3415
|
+
if (settled?.owner === owner && stationCheckInRetryable(settled.state)) {
|
|
3416
|
+
await send();
|
|
3417
|
+
}
|
|
3418
|
+
}, [settled, owner, send]);
|
|
3419
|
+
const { stations } = options;
|
|
3420
|
+
return useMemo12(() => {
|
|
3421
|
+
let state;
|
|
3422
|
+
if (!pending || finished && settled?.owner !== owner) {
|
|
3423
|
+
state = { status: "none" };
|
|
3424
|
+
} else if (settled?.owner === owner) {
|
|
3425
|
+
state = settled.state;
|
|
3426
|
+
} else {
|
|
3427
|
+
const where = {
|
|
3428
|
+
quest: pending.quest,
|
|
3429
|
+
station: checkInStation(pending, { stations })
|
|
3430
|
+
};
|
|
3431
|
+
state = signed.status === "ready" && !member ? { status: "sign-in-required", ...where } : { status: "checking", ...where };
|
|
3432
|
+
}
|
|
3433
|
+
return { ...state, retry };
|
|
3434
|
+
}, [
|
|
3435
|
+
pending,
|
|
3436
|
+
finished,
|
|
3437
|
+
settled,
|
|
3438
|
+
owner,
|
|
3439
|
+
signed.status,
|
|
3440
|
+
member,
|
|
3441
|
+
stations,
|
|
3442
|
+
retry
|
|
3443
|
+
]);
|
|
3444
|
+
}
|
|
3445
|
+
|
|
3373
3446
|
// src/react/offers.ts
|
|
3374
|
-
import { useCallback as
|
|
3447
|
+
import { useCallback as useCallback11, useMemo as useMemo13 } from "react";
|
|
3375
3448
|
function useOffers() {
|
|
3376
3449
|
const relay = useRelay();
|
|
3377
3450
|
return useRelayQuery(
|
|
@@ -3386,12 +3459,12 @@ function useRedeemOffer() {
|
|
|
3386
3459
|
{ invalidates: [relayKeys.offers, relayKeys.balances] }
|
|
3387
3460
|
);
|
|
3388
3461
|
const { mutateAsync } = mutation;
|
|
3389
|
-
const redeem =
|
|
3462
|
+
const redeem = useCallback11(
|
|
3390
3463
|
// The mutation's error state carries the failure; redeem answers null for it.
|
|
3391
3464
|
(offer) => mutateAsync(offer).catch(() => null),
|
|
3392
3465
|
[mutateAsync]
|
|
3393
3466
|
);
|
|
3394
|
-
return
|
|
3467
|
+
return useMemo13(
|
|
3395
3468
|
() => ({ ...mutation, redeem, retry: replay, busy: mutation.isPending }),
|
|
3396
3469
|
[mutation, redeem, replay]
|
|
3397
3470
|
);
|
|
@@ -3475,6 +3548,7 @@ export {
|
|
|
3475
3548
|
useSignInOptions,
|
|
3476
3549
|
useSignInWallets,
|
|
3477
3550
|
useSignOut,
|
|
3551
|
+
useStationCheckIn,
|
|
3478
3552
|
useTelegramAccount,
|
|
3479
3553
|
useTieredRewards,
|
|
3480
3554
|
useWalletDiscovery,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as z from 'zod';
|
|
2
|
-
import { T as TrackerSkipCode, S as SkipEnrollment } from './tracker-data-
|
|
2
|
+
import { T as TrackerSkipCode, S as SkipEnrollment } from './tracker-data-2BYXZjsN.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* The longest wording Relay stores: a checkbox label with a link to the policy fits.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{$b as He,Ad as at,Ae as kt,De as vt,Di as vr,Ee as yt,Ei as Lt,Fe as bt,Fi as Bt,Ge as E,Gi as Dt,Hd as nt,He as St,Hi as Nt,Ii as yr,J as de,Ja as Ae,Jd as ot,Jf as ee,K as me,Ka as xe,Ki as br,L as ge,La as sr,Le as x,Lf as D,M as he,Ma as V,Mb as Ue,Mi as It,N as fe,Nb as We,Ni as Ot,O as pe,Oa as Me,Oe as hr,Of as $t,Oi as re,P as we,Pa as cr,Q as ke,Qa as ir,R as ve,Ra as $e,Rb as Ze,Tb as Fe,Td as st,Ua as ur,Ub as Ve,Ud as ct,Uh as Pt,Va as ze,Vb as Ge,Ve as y,Wa as lr,Wb as S,Wc as _,We as Et,Wf as te,Xa as dr,Xc as Ye,Xd as it,Xe as M,Yc as H,Yd as ut,Yf as zt,Za as Re,Zb as _e,Zc as Xe,Ze as fr,_b as G,_g as jt,a as A,ab as mr,b as oe,bb as gr,c as T,ca as ye,cc as Je,ce as lt,cj as Kt,d as U,da as be,ea as nr,ee as dt,eg as Rt,f as le,fa as Se,fe as mt,fh as Tt,ge as gt,ha as or,he as ht,ia as Ee,ib as je,ie as ft,jb as Te,ka as L,lb as Pe,ma as F,mb as Le,na as qe,nb as Be,ob as De,od as et,of as pr,pb as Ne,pf as wr,qb as Ie,qf as kr,rd as tt,re as J,rf as qt,se as pt,sf as Ct,sj as Qt,ta as Ce,te as wt,uf as At,vb as B,ve as W,wb as Oe,wd as rt,wf as xt,xb as Ke,yb as Qe,ye as Y,yf as Mt,ze as X}from"./chunks/447P2VLY.js";import{Cb as R,Ec as P,Kb as ce,Pd as ar,fc as ie,ic as Z,jc as ue,va as se,wc as Q}from"./chunks/EWU4OKSY.js";function Ut(e){if(!Number.isInteger(e)||e<0||e>255)throw new Error("Token decimals must be an integer from 0 to 255")}function Sr(e,r){Ut(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 Er(e,r){Ut(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 Zt(e,r={}){let{trigger:t,completion:a,requires:n,performance:c,retryCooldownMs:i,completionCooldownMs:u,authorBudgets:l=[],stations:f}=e,s=t.kind==="automatic"?t.tracker:void 0,k=s?.content===!0;if(c&&!k)throw new Error("Performance requires a content quest");if(!s&&l.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(k){if(a.kind!=="keyed"||a.across)throw new Error("Content quests complete once per content item");if(s.beneficiary!=="author"||s.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(f&&r.template)throw new Error("Reusable quest types cannot declare check-in stations: declare them on a quest written in code");if(f&&!pt(t))throw new Error("Stations are for quests a signed Solana transaction completes: a member-submitted manual() quest without input");if(t.kind==="automatic"&&!s){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 qr=["author"],Cr=["author","messageAuthor"];function Ft(e){if(!Je(e))return[];switch(e.kind){case"x-search":return Ue;case"discord-messages":return qr;case"discord-reactions":return Cr;case"custom":return["author",...e.accounts??[]]}}var Wt=new Map;function Ar(e){let r=e.kind==="discord-messages"&&e.text?"messages-text":e.kind,t=Wt.get(r);return t||(t=B(r==="messages-text"?De:r==="discord-messages"?Be:Ne),Wt.set(r,t)),t}function Vt(e){switch(e.kind){case"x-search":return;case"discord-messages":case"discord-reactions":return Ar(e);case"custom":return e.data}}function Ht(e,r){let t=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 t&&"badge"in t&&t.badge!==void 0?`Badge rewards can only be granted by quests or manually, not by ${r}`:t&&"group"in t&&t.group!==void 0?`Group membership rewards can only be granted by quests, not by ${r}`:null}function ae(e,r,t,a){for(let[n,c]of r.entries()){let i=Ht(c,a);i&&e.addIssue({code:"custom",message:i,path:[...t,n]})}}function ra(e){return y("badge",A("Badge",le,e))}function aa(e){return y("ledger",A("Point ledger",Tt,e))}function na(e){let{target:r,ledger:t,...a}=e,n=It.parse({...a,qualifiedBy:e.qualifiedBy.key,balance:M(t)}),c=Q(P(e.metrics),re.shape.target);return{key:n.key,describe:()=>n,score(i){let u=Ot.parse(i);return re.parse({target:r({metrics:c.parse(u.metrics)}),baseline:r({metrics:c.parse(u.baseline)})})}}}var Mr=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 et.strict().parse({kind:"streak",...e})},oa=e=>Ye.brand().parse({kind:"count",count:e}),sa=(e,r={})=>H.brand().parse({kind:"calendar",period:e,...r}),ca=({days:e})=>H.brand().parse({kind:"rolling",durationMs:e*864e5}),ia=e=>({kind:"quest",quest:e}),$r=Qt.superRefine((e,r)=>{let t=Ht(e.reward,"offers");t&&r.addIssue({code:"custom",message:t,path:["reward"]})});function ua(e){return y("offer",A("Offer",$r,e))}var zr=Kt.superRefine((e,r)=>{for(let t of["inviter","invitee"])ae(r,e.rewards[t],["rewards",t],"referral programs");for(let[t,a]of e.milestones.entries())ae(r,a.rewards,["milestones",t,"rewards"],"referral programs")});function la(e){let{qualification:r,inviterGroup:t,milestones:a,bonuses:n,...c}=e,i=A("Referral",zr,{...c,qualification:r.kind==="quest"?{kind:"quest",quest:r.quest.key}:r,...t?{inviterGroup:U.parse(t.key)}:{},milestones:a?.map(({key:u,...l})=>({...l,id:x({key:u,...l})})),bonuses:n?.map(({key:u,ledger:l,quests:f,...s})=>({...s,id:x({key:u,...s}),balance:M(l),quests:f?.map(k=>k.key)}))});return y("referral",i)}function da(e={}){return{kind:"earned",...e}}var Rr=Pt.superRefine((e,r)=>{for(let[t,a]of(e.settle?.prizes??[]).entries())ae(r,a.rewards,["settle","prizes",t,"rewards"],"leaderboard prizes")});function jr(e){let r=e.ties??"shared";return!e.settle||e.settle.ties===r?null:`Leaderboard${e.key?` "${e.key}"`:""} orders equal scores "${r}" in its live standings${e.ties===void 0?" (ties left out)":""} but "${e.settle.ties}" when it settles, so the ranks members see are not the ranks prizes pay. Set ties: "${e.settle.ties}" beside settle.ties to show the order prizes pay.`}function ma(e){let{ledger:r,group:t,score:a,settle:n,...c}=e,i=n?.pool,u=A("Leaderboard",Rr,{...c,...n?{settle:{...n,prizes:n.prizes??[],...i?{pool:{...i,...i.ledger===void 0?{}:{ledger:M(i.ledger)}}}:{}}}:{},balance:M(r),...t?{group:U.parse(t.key)}:{},score:a?.kind==="earned"?{...a,quests:a.quests?.map(f=>f.key)}:a}),l=jr(u);return l&&console.warn(l),y("leaderboard",u)}var ga={provider:"x",search:e=>Ge.parse({kind:"x-search",...e})};function b(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(!Gt(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)We.parse(i);return S.parse({kind:"custom",namespace:e,...n,data:B(Z({body:a.body,metrics:ue(Object.fromEntries(c.map(i=>[i,R().int().safe().nonnegative().optional()]))).optional()})),content:{metrics:c}})}if(!Gt(t))throw new Error(`customSource("${e}") needs a data schema: customSource(namespace, { data: z.object({ ... }) }) describes each record's data`);return S.parse({kind:"custom",namespace:e,...n,data:B(t)})}function Gt(e){return typeof e=="object"&&e!==null&&"_zod"in e}function ha(e){return y("tracker",A("Tracker",He,e))}function Tr(e={}){return Pe.parse({kind:"discord-messages",...e.text?{text:!0}:{}})}function Pr(){return Le.parse({kind:"discord-reactions"})}var fa={provider:"discord",grantRole:e=>Ie.parse({kind:"integration",provider:"discord",action:"grant-role",roleId:e}),postMessage(e){return mt.parse({provider:"discord",action:"post-message",...e})},messages:Tr,reactions:Pr,roles(e={}){return W.parse({provider:"discord",resource:"role",assignable:e.assignable??!1})},channels(e={}){return W.parse({provider:"discord",resource:"channel",types:e.types??["text","announcement"],...e.postable?{postable:!0}:{}})}},pa={postMessage(e){return dt.parse({provider:"telegram",action:"post-message",...e})},messages(){return b(me,{identities:["member"],data:be})},reactions(){return b(de,{identities:["member"],accounts:["messageAuthor"],data:ye})}},wa={shorts(){return b(ge,{identities:["member"],content:{body:Lt,metrics:Bt}})}},ka={videos(){return b(he,{identities:["member"],content:{body:Dt,metrics:Nt}})}};function Lr(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"||typeof r=="string"&&F(r)){if(a!==null&&!Se.safeParse(a).success)throw new Error("wallet.balances() on Solana takes an SPL or Token-2022 mint address (base58)");return{chain:r==="solana"?L:r,token:a}}if(typeof r=="string"&&Ce(r)){if(a!==null&&!qe(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||!Ee.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"')}function Br(e){let{chain:r="solana",program:t,instruction:a,mint:n,minAmount:c,signer:i="wallet"}=e;if(r!=="solana"&&!(typeof r=="string"&&F(r)))throw new Error('wallet.programActivity() reads "solana" (mainnet) or Solana devnet, solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1');if(i!=="wallet"&&i!=="any")throw new Error('wallet.programActivity() takes signer "wallet" or "any"');let u=Ze.safeParse({chain:r==="solana"?L:r,program:t,instruction:a??null,mint:n??null,minAmount:c??null,anySigner:i==="any"});if(!u.success){let l=u.error.issues[0];throw new Error(`wallet.programActivity()${l.path.length?` ${l.path.join(".")}`:""}: ${l.message}`)}return u.data}var va={balances(e){let r=Lr(e),t=b(fe,{identities:["wallet"],data:Ae});return S.parse({...t,balance:r})},programActivity(e){let r=Br(e),t=b(pe,{identities:["wallet"],data:xe});return S.parse({...t,activity:r})},nfts(e){let{collection:r}=e;if(typeof r!="string"||!V(r))throw new Error('wallet.nfts() takes an NFT collection such as "eip155:1/erc721:0x\u2026", "eip155:8453/erc1155:0x\u2026/1" or "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/nft:<collection mint>"');let t=b(we,{identities:["wallet"],data:Me}),a={collection:r};return S.parse({...t,nfts:a})},stake(e={}){let{chain:r="solana",voteAccount:t}=e,a=Fe.safeParse({chain:r==="solana"?L:r,voteAccount:t??null});if(!a.success)throw new Error(`wallet.stake() ${a.error.issues[0].path.join(".")}: ${a.error.issues[0].message}`);let n=b(ke,{identities:["wallet"],data:je});return S.parse({...n,stake:a.data})},programAccounts(e){let{chain:r="solana",idl:t,...a}=e,n=Ve.safeParse({...a,chain:r==="solana"?L:r,...t===void 0?{}:{idl:{program:a.program,source:"pasted",idl:t}}});if(!n.success)throw new Error(`wallet.programAccounts() ${n.error.issues[0].path.join(".")}: ${n.error.issues[0].message}`);let c=b(ve,{identities:["wallet"],data:Te});return S.parse({...c,programAccount:n.data})}},ya=()=>({provider:"domino",resource:"point-ledger"});function p(e,r){return r}var ba={pointLedger(e){let r={...e,kind:"point-ledger",default:e.default?U.parse(e.default.key):""};return p("point-ledger",Et.prefault(r.default).meta(r))},datetime(e){let r={...e,kind:"datetime",default:Y.parse(e.default)};return p("datetime",Y.default(r.default).meta(r))},resource(e){let r={...e,source:W.parse(e.source),kind:"resource",default:X.parse(e.default??"")};return p("resource",X.default(r.default).meta(r))},quiz(e){let r=J.parse(e.default);return p("quiz",J.default(r).meta({...e,default:r,kind:"quiz"}))},text(e){let{secret:r,...t}=e,a={...t,kind:"text",default:"default"in e?e.default:"",minLength:e.minLength??(r?0:1),maxLength:e.maxLength??2e3,multiline:e.multiline??!1,...r?{secret:r}:{}};return p("text",E(a).default(a.default).meta(a))},telegramChat(e){let r={...e,kind:"text",default:e.default??"",minLength:0,maxLength:64,multiline:!1,picker:"telegram-chat"};return p("text",se().max(r.maxLength).default(r.default).meta(r))},amount(e){if(!vt(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(!yt(e.default))throw new Error(`settings.chain() takes "solana", a Solana cluster ID 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(!V(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(!$e(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(!ze(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(!Re(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",R().int().min(e.min).max(e.max).default(e.default).meta({...e,kind:"integer"}))},boolean(e){return p("boolean",ce().default(e.default).meta({...e,kind:"boolean"}))},choice(e){return p("choice",P(e.options).default(e.default).meta({...e,kind:"choice"}))},object(e){return Z(e).strict()}};function Jt(e,r){let t=e.balanceChanges.find(a=>a.mint===r);return t?BigInt(t.delta):0n}function Ea(e,r){let t=Jt(e,r);return t>0n?t.toString():"0"}function qa(e,r){let t=Jt(e,r);return t<0n?(-t).toString():"0"}function Ca(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 Aa(e,r){return e.programs.includes(r)}function xa(e,r){return e.instructions?.find(t=>t.name===r)?.args??null}var Ma=e=>xt(e.key,e.name),$a=e=>Mt(e.key,e.title),za=(e,r)=>qt.parse({kind:"points",balance:M(e),amount:r}),Ra={text:(e={})=>({input:"text",constraints:ht.parse(e)}),url:(e={})=>({input:"url",constraints:ft.parse(e)}),photo:()=>"photo",quiz:()=>"quiz"};function ja(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 Yt=new WeakMap,Xt=new WeakMap;function er(e,r){let{tracker:t,beneficiary:a="author",on:n,where:c,enrollment:i,since:u,historical:l,content:f}=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:s}=t;if(!_e(s))throw new Error('Tracker triggers need attributable records: declare customSource(namespace, { identities: ["wallet"] }) or other identity kinds');if(f&&!G(s))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 k=Ft(s);if(!k.includes(a))throw new Error(s.kind==="custom"?`Tracker "${t.key}" has no "${a}" account: declare it in customSource(namespace, { accounts: ["${a}"] })`:`Tracker "${t.key}" pays ${new Intl.ListFormat("en",{type:"disjunction"}).format(k.map(m=>`"${m}"`))}, not "${a}"`);let q=at.parse({tracker:t.key,source:s.kind,on:f?"new-record":n??tt(s.kind,s.kind==="custom"?s.namespace:void 0),...c?{where:c}:{},beneficiary:a,...i==="required"?{enrollment:i}:{},...u&&u!=="activation"?{since:u}:{},...l&&l!==(f?"claim":"staff")?{historical:l}:{},...f?{content:f}:{}}),v=Vt(s),N=v?Qe(v,q.where):null;if(N)throw new Error(N);let j={kind:"automatic",tracker:q};v&&Yt.set(j,v);let o=G(s);return o&&Xt.set(j,o.metrics),j}function Ta(e){return e?er(e,"automatic"):{kind:"automatic"}}function Pa(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 er({...e,content:!0},"content")}function Dr(e){let{key:r,cost:t,...a}=e,n={...a,id:x(e),cost:typeof t=="number"?t:{balance:M(t.ledger)}};return a.scope==="author"?ct.parse(n):st.parse(n)}var La=Dr,Nr=(e=[])=>e.filter(r=>r.scope==="author"),tr=(e,r={})=>({kind:"keyed",key:e,...r.across?{across:r.across}:{}}),Ir=()=>tr(e=>{let r=e.action?.reference;if(!r)throw new Error("perStation() completes from a signed transaction whose memo names a station");return r}),Or=e=>{let{distinct:r,...t}=e;return{...Xe.parse({kind:"progress",window:{kind:"lifetime"},...t}),distinct:r}},Ba=()=>({kind:"untracked"}),Da=()=>({kind:"staff-handover"}),Na=()=>({kind:"automatic"});function Ia(e){let{key:r,tiers:t,...a}=e,n=x(e),c=Ct.parse({id:n,...a,tiers:t.map(({key:i,...u})=>({...u,id:x({key:i,...u})}))});return y("tiered-reward",{key:c.id,tier:i=>At.parse({kind:"tier",reward:c,tier:i})})}var Kr=()=>({kind:"once"});function Qr(e={}){return{kind:"accept",...e}}function Ur(e){return{kind:"review",...e}}var $={accept:Qr,defer:e=>({kind:"defer",...e}),progress:e=>({kind:"progress",...e}),reject:e=>({kind:"reject",...e}),review:Ur};function _t(e){let r=e.kind==="reject"&&e.code!==void 0?ot(e.code):null;if(r)throw new Error(r)}var Oa={quiz(e,r={}){let t=Rt.parse(e),a=Object.keys(t),n=R().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(l=>Object.hasOwn(c.answers,l)),u=a.filter(l=>c.answers[l]===t[l]).length;return i&&u>=n?$.accept():$.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"?$.review({reason:a.reason}):$.reject({reason:a.reason}):a.kind==="pass"?$.accept():$.reject({reason:a.reason})}}},Wr={once:Kr,keyed:tr,streak:Mr,progress:Or,perStation:Ir};function rr(e){return function(t){let a=x(t),n=`${e?"Quest type":"Quest"} "${a}"`;if(t.rewards===void 0)throw new Error(`${n}: rewards is missing. Return [] for a quest that gives none.`);let c=[...new Set((t.integrations??[]).map(o=>ut.parse(o.provider)))],i=c.flatMap(o=>{let m=it.safeParse(o);return m.success?[m.data]:[]}),u=t.trigger.kind==="automatic"&&t.trigger.tracker?.content===!0,l=t.trigger.kind==="automatic"&&t.trigger.tracker!==void 0,f=t.completion,s=typeof f=="function"?f(Wr):f;if(u&&s!==void 0)throw new Error("A content quest completes once per content item: remove its completion");if(!u&&s===void 0)throw new Error("A quest needs a completion, such as once(), keyed(...), streak(...) or progress(...)");let k=Nr(t.budgets),q=t.stations?wt.parse(t.stations):void 0;if(Zt({trigger:t.trigger,completion:s??{kind:"keyed"},requires:t.requires??[],authorBudgets:k,performance:t.performance?_.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},...q?{stations:q}:{}},{template:e}),t.retryCooldownMs!==void 0&&!ee.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&&!ee.safeParse(t.completionCooldownMs).success)throw new Error("completionCooldownMs must be whole milliseconds from 1000 (one second) to 604800000 (seven days)");if(t.performance){let o=Xt.get(t.trigger)??[],m=t.performance.metrics.filter(g=>!o.includes(g));if(m.length)throw new Error(`The tracker's source does not measure ${m.join(", ")}`)}if(t.trigger.kind==="manual"&&t.trigger.input!=="none"&&!t.evaluate)throw new Error("Evidence quests require an evaluator");let v=Object.fromEntries(Object.entries(t.settings.shape).map(([o,m])=>{let g=kt.safeParse(m.meta());if(!g.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 })`);if(g.data.kind==="text"&&g.data.secret&&g.data.default!=="")throw new Error(`Secret setting "${o}" must default to "": set its value in Console, not in source or deploy settings`);return[o,g.data]}));for(let o of rt(t.trigger.kind==="automatic"?t.trigger.tracker?.where:void 0))if(!bt(v[o]))throw new Error(`The tracker filter compares with setting "${o}", which is not an integer or amount setting`);function N(o){try{return j(o)}catch(m){throw oe(n,m)}}function j(o){let{performance:m}=t,g=T("settings",()=>t.settings.parse(o)),I=St(v,g),z=T("rewards",()=>$t.parse(typeof t.rewards=="function"?t.rewards({settings:g}):t.rewards)),C=T("announcements",()=>ie(gt).max(3,"A quest posts at most three announcements").parse((typeof t.announcements=="function"?t.announcements({settings:g}):t.announcements)??[])),h=t.trigger.kind==="automatic"&&t.trigger.tracker!==void 0;for(let d of C){let K=lt(d.text),w="segments"in K&&K.segments.some(ne=>ne.kind==="placeholder"&&ne.name==="author");if(!h&&w)throw new Error("An announcement names {author} only on a quest with an automatic tracker trigger");if(!h&&d.replyToTriggeringMessage)throw new Error("An announcement replies to the triggering message only on a quest with an automatic tracker trigger")}let O=[...z.flatMap(d=>d.kind==="integration"?[d.provider]:[]),...C.flatMap(d=>d.provider==="discord"?["discord"]:[]),...Object.values(v).flatMap(d=>d.kind==="resource"&&d.source.provider!=="domino"?[d.source.provider]:[])];for(let d of O)if(!i.includes(d))throw new Error(`Declare the ${d} integration on this quest`);return zt.parse({quest:a,evaluatorProtocol:te,title:typeof t.title=="function"?t.title({settings:g}):t.title,presentation:t.presentation?.({settings:g})??{},fields:v,values:I,rewards:z,...C.length?{announcements:C}:{},humanReview:t.review?.({settings:g})?.enabled??!0,trigger:t.trigger,...m?{performance:T("performance",()=>_.parse({metrics:m.metrics,maxAgeMs:m.maxAgeMs}))}:{},integrations:i,...c.length>i.length?{integrationModules:c}:{},completion:s?s.kind==="progress"?{kind:s.kind,goal:s.goal,window:s.window,repeat:s.repeat}:s.kind==="streak"?s:s.kind==="keyed"&&s.across?{kind:s.kind,across:s.across}:{kind:s.kind}:{kind:"keyed"},visibility:t.visibility??"visible",profile:t.profile??{visible:!1},budgets:(t.budgets??[]).filter(d=>d.scope!=="author"),...k.length?{authorBudgets:k}:{},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},...q?{stations:q}:{}})}return y("quest",{protocol:te,key:a,describe:N,async evaluate(o){let m=t.settings.parse(o.settings),g=l?nt.parse(o.tracker):null,I=Yt.get(t.trigger),z=g&&I?Oe(I,g.record.data):null;if(z)return D.parse({kind:"reject",reason:`The record's data does not match the data schema this quest was built with: ${z.path} ${z.reason}`});let C=g;if(o.performance){if(!t.performance)throw new Error("Quest has no performance evaluator");let d=jt.parse(o.performance),K=Q(P(t.performance.metrics),R().int().safe().nonnegative()).parse(d.metrics),w=await t.performance.evaluate({settings:m,member:o.member,tracker:C,metrics:K,observedAt:d.observedAt});if(!w)throw new Error("Performance evaluator returned no decision");if(w.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 _t(w),D.parse(w.kind==="accept"?{kind:"accept",rewards:d.rewards}:w.kind==="review"&&o.humanReview?{kind:"review",reason:w.reason,rewards:d.rewards}:{kind:"reject",reason:w.reason,...w.kind==="review"?{requestedReview:!0}:w.code===void 0?{}:{code:w.code}})}let h=t.evaluate?await t.evaluate({settings:m,member:o.member,input:o.input,tracker:C,action:o.action??null,eligibleAt:o.eligibleAt,calendar:o.calendar,now:o.now,review:o.review,trackers:Ke(o.trackers),wallet:o.wallet,images:o.images,...o.telegram?{telegram:o.telegram}:{},...Object.fromEntries(i.map(d=>[d,o[d]]))}):$.accept();if(!h)throw new Error("Evaluator returned no decision");if(_t(h),h.kind==="review"&&!o.humanReview)return D.parse({kind:"reject",reason:h.reason,requestedReview:!0});(h.kind==="accept"||h.kind==="review")&&h.completionKey!==void 0&&s?.kind!=="keyed"&&o.diagnose?.({code:"completion-key-ignored",message:Zr(s,h.completionKey)});let O={...o,settings:m,tracker:g,action:o.action??null};return D.parse(h.kind==="accept"||h.kind==="review"?{...h,rewards:h.rewards??o.rewards,...s?.kind==="keyed"||s?.kind==="progress"?{completionKey:s.kind==="progress"?s.distinct(O):h.completionKey??s.key(O)}:{}}:h)}})}}function Zr(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 Ka=rr(!1),Qa=rr(!0);export{br as CapabilityError,Ta as automatic,Na as automaticFulfillment,Ma as badge,wr as balanceAtLeast,La as budget,sa as calendar,yr as capabilityErrorCodes,pr as completed,Pa as content,Ee as cosmosDenomSchema,or as cosmosNetworkSchema,oa as count,b as customSource,$ as decision,ra as defineBadge,hr as defineCampaign,vr as defineDashboard,na as defineEngagementReward,fr as defineGroup,ma as defineLeaderboard,aa as defineLedger,ua as defineOffer,Ka as defineQuest,Qa as defineQuestType,la as defineReferral,Ia as defineTieredReward,ha as defineTracker,fa as discord,da as earned,Oa as evaluators,Ra as evidence,Er as formatUnits,$a as groupMembership,kr as inGroup,xa as instruction,Aa as invoked,$e as isContractCall,ze as isContractEvent,qe as isEvmAddress,Ce as isEvmChainId,V as isNftCollection,Re as isSolanaProgram,tr as keyed,jr as leaderboardTiesWarning,nr as limits,ja as manual,lr as maxWalletEventLogs,dr as maxWalletEventLookback,gr as maxWalletTransactionLookback,mr as maxWalletTransactions,Kr as once,ir as parseContractCall,ur as parseContractEvent,cr as parseContractFunction,sr as parseNftCollection,Sr as parseUnits,Ir as perStation,ya as pointLedgers,za as points,Or as progress,ia as questCompleted,Ea as received,ca as rolling,ba as settings,qa as spent,Da as staffHandover,Mr as streak,Ca as swapped,pa as telegram,ka as tiktok,B as trackerDataSchema,nt as trackerTriggerContextSchema,Ba as untracked,va as wallet,ga as x,wa as youtube,ar as z};
|
|
1
|
+
import{$b as Ye,$e as kr,Ad as ot,Ae as ee,Af as Rt,Be as te,Ce as bt,Fe as St,Fi as Sr,Ge as Et,Gi as Nt,Hd as st,He as qt,Hi as It,Ie as q,Ii as Ot,J as he,Ja as xe,Jd as ct,Je as At,Ji as Kt,K as ge,Ka as Me,Ki as Er,L as pe,La as ur,Lf as re,M as fe,Ma as G,Mb as Ze,Mi as qr,N as we,Nb as Fe,Ne as x,Nf as N,O as ke,Oa as ze,Oi as Qt,P as ve,Pa as lr,Pi as Ut,Q as ye,Qa as dr,Qe as wr,Qf as jt,Qi as ne,R as be,Ra as Re,Rb as Ve,Tb as Ge,Td as it,Ua as mr,Ub as _e,Ud as ut,Va as je,Vb as He,Wa as hr,Wb as E,Wc as H,Wh as Dt,Xa as gr,Xc as et,Xd as lt,Xe as b,Yc as J,Yd as dt,Ye as Ct,Yf as ae,Za as Te,Zb as Je,Zc as tt,Ze as M,_b as _,_f as Tt,a as $,ab as pr,ah as Lt,b as ce,bb as fr,c as P,ca as Se,cc as Xe,ce as mt,d as W,da as Ee,ea as cr,ee as ht,ej as Wt,f as me,fa as qe,fe as gt,ge as pt,gg as Pt,ha as ir,he as ft,hh as Bt,ia as Ae,ib as Pe,ie as wt,jb as Le,ka as B,lb as Be,ma as V,mb as De,na as Ce,nb as Ne,ob as Ie,od as rt,pb as Oe,qb as Ke,qf as vr,rd as at,re as Y,rf as yr,se as kt,sf as br,ta as $e,te as vt,tf as $t,uf as xt,uj as Zt,vb as D,ve as X,wb as Qe,wd as nt,we as yt,wf as Mt,xb as Ue,xe as Z,yb as We,yf as zt}from"./chunks/A7G5P76B.js";import{Cb as j,Ec as L,Kb as ue,Pd as sr,fc as le,ic as F,jc as de,va as ie,wc as U}from"./chunks/EWU4OKSY.js";function Ft(e){if(!Number.isInteger(e)||e<0||e>255)throw new Error("Token decimals must be an integer from 0 to 255")}function Ar(e,r){Ft(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 Cr(e,r){Ft(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:"")}var $r=class extends Error{constructor(e,r){super(e),this.code=r,this.name="QuestShapeError"}code};function Gt(e,r={}){let{trigger:t,completion:a,requires:n,performance:c,retryCooldownMs:i,completionCooldownMs:u,authorBudgets:l=[],stations:p,gallery:o}=e,w=t.kind==="automatic"?t.tracker:void 0,y=w?.content===!0;if(c&&!y)throw new Error("Performance requires a content quest");if(!w&&l.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(y){if(a.kind!=="keyed"||a.across)throw new Error("Content quests complete once per content item");if(w.beneficiary!=="author"||w.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(p&&r.template)throw new Error("Reusable quest types cannot declare check-in stations: declare them on a quest written in code");if(p&&!kt(t))throw new Error("Stations are for quests a signed Solana transaction completes: a member-submitted manual() quest without input");if(o&&r.template)throw new Error("Reusable quest types cannot declare a photo gallery: declare it on a quest written in code");if(o&&!r.authoring&&!(t.kind==="manual"&&t.input==="photo"))throw new $r("A photo gallery is for a quest whose input is a photo: manual({ input: evidence.photo() })","gallery-requires-photo");if(o&&!X.some(k=>k===o.kind))throw new Error(`Unknown gallery kind "${o.kind}": use ${X.map(k=>`"${k}"`).join(" or ")}`);if(t.kind==="automatic"&&!w){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 xr=["author"],Mr=["author","messageAuthor"];function _t(e){if(!Xe(e))return[];switch(e.kind){case"x-search":return Ze;case"discord-messages":return xr;case"discord-reactions":return Mr;case"custom":return["author",...e.accounts??[]]}}var Vt=new Map;function zr(e){let r=e.kind==="discord-messages"&&e.text?"messages-text":e.kind,t=Vt.get(r);return t||(t=D(r==="messages-text"?Ie:r==="discord-messages"?Ne:Oe),Vt.set(r,t)),t}function Ht(e){switch(e.kind){case"x-search":return;case"discord-messages":case"discord-reactions":return zr(e);case"custom":return e.data}}function Xt(e,r){let t=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 t&&"badge"in t&&t.badge!==void 0?`Badge rewards can only be granted by quests or manually, not by ${r}`:t&&"group"in t&&t.group!==void 0?`Group membership rewards can only be granted by quests, not by ${r}`:null}function oe(e,r,t,a){for(let[n,c]of r.entries()){let i=Xt(c,a);i&&e.addIssue({code:"custom",message:i,path:[...t,n]})}}function ca(e){return b("badge",$("Badge",me,e))}function ia(e){return b("ledger",$("Point ledger",Bt,e))}function ua(e){let{target:r,ledger:t,...a}=e,n=Qt.parse({...a,qualifiedBy:e.qualifiedBy.key,balance:M(t)}),c=U(L(e.metrics),ne.shape.target);return{key:n.key,describe:()=>n,score(i){let u=Ut.parse(i);return ne.parse({target:r({metrics:c.parse(u.metrics)}),baseline:r({metrics:c.parse(u.baseline)})})}}}var jr=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 rt.strict().parse({kind:"streak",...e})},la=e=>et.brand().parse({kind:"count",count:e}),da=(e,r={})=>J.brand().parse({kind:"calendar",period:e,...r}),ma=({days:e})=>J.brand().parse({kind:"rolling",durationMs:e*864e5}),ha=e=>({kind:"quest",quest:e}),Tr=Zt.superRefine((e,r)=>{let t=Xt(e.reward,"offers");t&&r.addIssue({code:"custom",message:t,path:["reward"]})});function ga(e){return b("offer",$("Offer",Tr,e))}var Pr=Wt.superRefine((e,r)=>{for(let t of["inviter","invitee"])oe(r,e.rewards[t],["rewards",t],"referral programs");for(let[t,a]of e.milestones.entries())oe(r,a.rewards,["milestones",t,"rewards"],"referral programs")});function pa(e){let{qualification:r,inviterGroup:t,milestones:a,bonuses:n,...c}=e,i=$("Referral",Pr,{...c,qualification:r.kind==="quest"?{kind:"quest",quest:r.quest.key}:r,...t?{inviterGroup:W.parse(t.key)}:{},milestones:a?.map(({key:u,...l})=>({...l,id:x({key:u,...l})})),bonuses:n?.map(({key:u,ledger:l,quests:p,...o})=>({...o,id:x({key:u,...o}),balance:M(l),quests:p?.map(w=>w.key)}))});return b("referral",i)}function fa(e={}){return{kind:"earned",...e}}var Lr=Dt.superRefine((e,r)=>{for(let[t,a]of(e.settle?.prizes??[]).entries())oe(r,a.rewards,["settle","prizes",t,"rewards"],"leaderboard prizes")});function Br(e){let r=e.ties??"shared";return!e.settle||e.settle.ties===r?null:`Leaderboard${e.key?` "${e.key}"`:""} orders equal scores "${r}" in its live standings${e.ties===void 0?" (ties left out)":""} but "${e.settle.ties}" when it settles, so the ranks members see are not the ranks prizes pay. Set ties: "${e.settle.ties}" beside settle.ties to show the order prizes pay.`}function wa(e){let{ledger:r,group:t,score:a,settle:n,...c}=e,i=n?.pool,u=$("Leaderboard",Lr,{...c,...n?{settle:{...n,prizes:n.prizes??[],...i?{pool:{...i,...i.ledger===void 0?{}:{ledger:M(i.ledger)}}}:{}}}:{},balance:M(r),...t?{group:W.parse(t.key)}:{},score:a?.kind==="earned"?{...a,quests:a.quests?.map(p=>p.key)}:a}),l=Br(u);return l&&console.warn(l),b("leaderboard",u)}var ka={provider:"x",search:e=>He.parse({kind:"x-search",...e})};function S(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(!Jt(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)Fe.parse(i);return E.parse({kind:"custom",namespace:e,...n,data:D(F({body:a.body,metrics:de(Object.fromEntries(c.map(i=>[i,j().int().safe().nonnegative().optional()]))).optional()})),content:{metrics:c}})}if(!Jt(t))throw new Error(`customSource("${e}") needs a data schema: customSource(namespace, { data: z.object({ ... }) }) describes each record's data`);return E.parse({kind:"custom",namespace:e,...n,data:D(t)})}function Jt(e){return typeof e=="object"&&e!==null&&"_zod"in e}function va(e){return b("tracker",$("Tracker",Ye,e))}function Dr(e={}){return Be.parse({kind:"discord-messages",...e.text?{text:!0}:{}})}function Nr(){return De.parse({kind:"discord-reactions"})}var ya={provider:"discord",grantRole:e=>Ke.parse({kind:"integration",provider:"discord",action:"grant-role",roleId:e}),postMessage(e){return gt.parse({provider:"discord",action:"post-message",...e})},messages:Dr,reactions:Nr,roles(e={}){return Z.parse({provider:"discord",resource:"role",assignable:e.assignable??!1})},channels(e={}){return Z.parse({provider:"discord",resource:"channel",types:e.types??["text","announcement"],...e.postable?{postable:!0}:{}})}},ba={postMessage(e){return ht.parse({provider:"telegram",action:"post-message",...e})},messages(){return S(ge,{identities:["member"],data:Ee})},reactions(){return S(he,{identities:["member"],accounts:["messageAuthor"],data:Se})}},Sa={shorts(){return S(pe,{identities:["member"],content:{body:Nt,metrics:It}})}},Ea={videos(){return S(fe,{identities:["member"],content:{body:Ot,metrics:Kt}})}};function Ir(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"||typeof r=="string"&&V(r)){if(a!==null&&!qe.safeParse(a).success)throw new Error("wallet.balances() on Solana takes an SPL or Token-2022 mint address (base58)");return{chain:r==="solana"?B:r,token:a}}if(typeof r=="string"&&$e(r)){if(a!==null&&!Ce(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||!Ae.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"')}function Or(e){let{chain:r="solana",program:t,instruction:a,mint:n,minAmount:c,signer:i="wallet"}=e;if(r!=="solana"&&!(typeof r=="string"&&V(r)))throw new Error('wallet.programActivity() reads "solana" (mainnet) or Solana devnet, solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1');if(i!=="wallet"&&i!=="any")throw new Error('wallet.programActivity() takes signer "wallet" or "any"');let u=Ve.safeParse({chain:r==="solana"?B:r,program:t,instruction:a??null,mint:n??null,minAmount:c??null,anySigner:i==="any"});if(!u.success){let l=u.error.issues[0];throw new Error(`wallet.programActivity()${l.path.length?` ${l.path.join(".")}`:""}: ${l.message}`)}return u.data}var qa={balances(e){let r=Ir(e),t=S(we,{identities:["wallet"],data:xe});return E.parse({...t,balance:r})},programActivity(e){let r=Or(e),t=S(ke,{identities:["wallet"],data:Me});return E.parse({...t,activity:r})},nfts(e){let{collection:r}=e;if(typeof r!="string"||!G(r))throw new Error('wallet.nfts() takes an NFT collection such as "eip155:1/erc721:0x\u2026", "eip155:8453/erc1155:0x\u2026/1" or "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/nft:<collection mint>"');let t=S(ve,{identities:["wallet"],data:ze}),a={collection:r};return E.parse({...t,nfts:a})},stake(e={}){let{chain:r="solana",voteAccount:t}=e,a=Ge.safeParse({chain:r==="solana"?B:r,voteAccount:t??null});if(!a.success)throw new Error(`wallet.stake() ${a.error.issues[0].path.join(".")}: ${a.error.issues[0].message}`);let n=S(ye,{identities:["wallet"],data:Pe});return E.parse({...n,stake:a.data})},programAccounts(e){let{chain:r="solana",idl:t,...a}=e,n=_e.safeParse({...a,chain:r==="solana"?B:r,...t===void 0?{}:{idl:{program:a.program,source:"pasted",idl:t}}});if(!n.success)throw new Error(`wallet.programAccounts() ${n.error.issues[0].path.join(".")}: ${n.error.issues[0].message}`);let c=S(be,{identities:["wallet"],data:Le});return E.parse({...c,programAccount:n.data})}},Aa=()=>({provider:"domino",resource:"point-ledger"});function f(e,r){return r}var Ca={pointLedger(e){let r={...e,kind:"point-ledger",default:e.default?W.parse(e.default.key):""};return f("point-ledger",Ct.prefault(r.default).meta(r))},datetime(e){let r={...e,kind:"datetime",default:ee.parse(e.default)};return f("datetime",ee.default(r.default).meta(r))},resource(e){let r={...e,source:Z.parse(e.source),kind:"resource",default:te.parse(e.default??"")};return f("resource",te.default(r.default).meta(r))},quiz(e){let r=Y.parse(e.default);return f("quiz",Y.default(r).meta({...e,default:r,kind:"quiz"}))},text(e){let{secret:r,...t}=e,a={...t,kind:"text",default:"default"in e?e.default:"",minLength:e.minLength??(r?0:1),maxLength:e.maxLength??2e3,multiline:e.multiline??!1,...r?{secret:r}:{}};return f("text",q(a).default(a.default).meta(a))},telegramChat(e){let r={...e,kind:"text",default:e.default??"",minLength:0,maxLength:64,multiline:!1,picker:"telegram-chat"};return f("text",ie().max(r.maxLength).default(r.default).meta(r))},amount(e){if(!St(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 f("text",q(r).default(r.default).meta(r))},chain(e){if(!Et(e.default))throw new Error(`settings.chain() takes "solana", a Solana cluster ID 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 f("text",q(r).transform(t=>t).default(r.default).meta(r))},nft(e){if(!G(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 f("text",q(r).transform(t=>t).default(r.default).meta(r))},contractCall(e){if(!Re(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 f("text",q(r).transform(t=>t).default(r.default).meta(r))},contractEvent(e){if(!je(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 f("text",q(r).transform(t=>t).default(r.default).meta(r))},solanaProgram(e){if(!Te(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 f("text",q(r).transform(t=>t).default(r.default).meta(r))},integer(e){return f("integer",j().int().min(e.min).max(e.max).default(e.default).meta({...e,kind:"integer"}))},boolean(e){return f("boolean",ue().default(e.default).meta({...e,kind:"boolean"}))},choice(e){return f("choice",L(e.options).default(e.default).meta({...e,kind:"choice"}))},object(e){return F(e).strict()}};function er(e,r){let t=e.balanceChanges.find(a=>a.mint===r);return t?BigInt(t.delta):0n}function xa(e,r){let t=er(e,r);return t>0n?t.toString():"0"}function Ma(e,r){let t=er(e,r);return t<0n?(-t).toString():"0"}function za(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 Ra(e,r){return e.programs.includes(r)}function ja(e,r){return e.instructions?.find(t=>t.name===r)?.args??null}var Ta=e=>zt(e.key,e.name),Pa=e=>Rt(e.key,e.title),La=(e,r)=>$t.parse({kind:"points",balance:M(e),amount:r}),Ba={text:(e={})=>({input:"text",constraints:ft.parse(e)}),url:(e={})=>({input:"url",constraints:wt.parse(e)}),photo:()=>"photo",quiz:()=>"quiz"};function Da(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 tr=new WeakMap,rr=new WeakMap;function ar(e,r){let{tracker:t,beneficiary:a="author",on:n,where:c,enrollment:i,since:u,historical:l,content:p}=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:o}=t;if(!Je(o))throw new Error('Tracker triggers need attributable records: declare customSource(namespace, { identities: ["wallet"] }) or other identity kinds');if(p&&!_(o))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 w=_t(o);if(!w.includes(a))throw new Error(o.kind==="custom"?`Tracker "${t.key}" has no "${a}" account: declare it in customSource(namespace, { accounts: ["${a}"] })`:`Tracker "${t.key}" pays ${new Intl.ListFormat("en",{type:"disjunction"}).format(w.map(s=>`"${s}"`))}, not "${a}"`);let y=ot.parse({tracker:t.key,source:o.kind,on:p?"new-record":n??at(o.kind,o.kind==="custom"?o.namespace:void 0),...c?{where:c}:{},beneficiary:a,...i==="required"?{enrollment:i}:{},...u&&u!=="activation"?{since:u}:{},...l&&l!==(p?"claim":"staff")?{historical:l}:{},...p?{content:p}:{}}),k=Ht(o),A=k?We(k,y.where):null;if(A)throw new Error(A);let T={kind:"automatic",tracker:y};k&&tr.set(T,k);let I=_(o);return I&&rr.set(T,I.metrics),T}function Na(e){return e?ar(e,"automatic"):{kind:"automatic"}}function Ia(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 ar({...e,content:!0},"content")}function Kr(e){let{key:r,cost:t,...a}=e,n={...a,id:x(e),cost:typeof t=="number"?t:{balance:M(t.ledger)}};return a.scope==="author"?ut.parse(n):it.parse(n)}var Oa=Kr,Qr=(e=[])=>e.filter(r=>r.scope==="author"),nr=(e,r={})=>({kind:"keyed",key:e,...r.across?{across:r.across}:{}}),Ur=()=>nr(e=>{let r=e.action?.reference;if(!r)throw new Error("perStation() completes from a check-in at a station: a signed transaction whose memo names one, or a station's code");return r}),Wr=e=>{let{distinct:r,...t}=e;return{...tt.parse({kind:"progress",window:{kind:"lifetime"},...t}),distinct:r}},Ka=()=>({kind:"untracked"}),Qa=()=>({kind:"staff-handover"}),Ua=()=>({kind:"automatic"});function Wa(e){let{key:r,tiers:t,...a}=e,n=x(e),c=xt.parse({id:n,...a,tiers:t.map(({key:i,...u})=>({...u,id:x({key:i,...u})}))});return b("tiered-reward",{key:c.id,tier:i=>Mt.parse({kind:"tier",reward:c,tier:i})})}var Zr=()=>({kind:"once"});function Fr(e={}){return{kind:"accept",...e}}function Vr(e){return{kind:"review",...e}}var z={accept:Fr,defer:e=>({kind:"defer",...e}),progress:e=>({kind:"progress",...e}),reject:e=>({kind:"reject",...e}),review:Vr};function Yt(e){let r=e.kind==="reject"&&e.code!==void 0?ct(e.code):null;if(r)throw new Error(r)}var Za={quiz(e,r={}){let t=Pt.parse(e),a=Object.keys(t),n=j().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(l=>Object.hasOwn(c.answers,l)),u=a.filter(l=>c.answers[l]===t[l]).length;return i&&u>=n?z.accept():z.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"?z.review({reason:a.reason}):z.reject({reason:a.reason}):a.kind==="pass"?z.accept():z.reject({reason:a.reason})}}},Gr={once:Zr,keyed:nr,streak:jr,progress:Wr,perStation:Ur};function or(e){return function(t){let a=x(t),n=`${e?"Quest type":"Quest"} "${a}"`;if(t.rewards===void 0)throw new Error(`${n}: rewards is missing. Return [] for a quest that gives none.`);let c=[...new Set((t.integrations??[]).map(s=>dt.parse(s.provider)))],i=c.flatMap(s=>{let h=lt.safeParse(s);return h.success?[h.data]:[]}),u=t.trigger.kind==="automatic"&&t.trigger.tracker?.content===!0,l=t.trigger.kind==="automatic"&&t.trigger.tracker!==void 0,p=t.completion,o=typeof p=="function"?p(Gr):p;if(u&&o!==void 0)throw new Error("A content quest completes once per content item: remove its completion");if(!u&&o===void 0)throw new Error("A quest needs a completion, such as once(), keyed(...), streak(...) or progress(...)");let w=Qr(t.budgets),y=t.stations?vt.parse(t.stations):void 0,k=t.gallery?yt.parse(t.gallery):void 0;if(Gt({trigger:t.trigger,completion:o??{kind:"keyed"},requires:t.requires??[],authorBudgets:w,performance:t.performance?H.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},...y?{stations:y}:{},...k?{gallery:k}:{}},{template:e,authoring:!0}),t.retryCooldownMs!==void 0&&!re.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&&!re.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=rr.get(t.trigger)??[],h=t.performance.metrics.filter(m=>!s.includes(m));if(h.length)throw new Error(`The tracker's source does not measure ${h.join(", ")}`)}if(t.trigger.kind==="manual"&&t.trigger.input!=="none"&&!t.evaluate)throw new Error("Evidence quests require an evaluator");let A=Object.fromEntries(Object.entries(t.settings.shape).map(([s,h])=>{let m=bt.safeParse(h.meta());if(!m.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 })`);if(m.data.kind==="text"&&m.data.secret&&m.data.default!=="")throw new Error(`Secret setting "${s}" must default to "": set its value in Console, not in source or deploy settings`);return[s,m.data]}));for(let s of nt(t.trigger.kind==="automatic"?t.trigger.tracker?.where:void 0))if(!qt(A[s]))throw new Error(`The tracker filter compares with setting "${s}", which is not an integer or amount setting`);function T(s){try{return I(s)}catch(h){throw ce(n,h)}}function I(s){let{performance:h}=t,m=P("settings",()=>t.settings.parse(s)),O=At(A,m),R=P("rewards",()=>jt.parse(typeof t.rewards=="function"?t.rewards({settings:m}):t.rewards)),C=P("announcements",()=>le(pt).max(3,"A quest posts at most three announcements").parse((typeof t.announcements=="function"?t.announcements({settings:m}):t.announcements)??[])),g=t.trigger.kind==="automatic"&&t.trigger.tracker!==void 0;for(let d of C){let Q=mt(d.text),v="segments"in Q&&Q.segments.some(se=>se.kind==="placeholder"&&se.name==="author");if(!g&&v)throw new Error("An announcement names {author} only on a quest with an automatic tracker trigger");if(!g&&d.replyToTriggeringMessage)throw new Error("An announcement replies to the triggering message only on a quest with an automatic tracker trigger")}let K=[...R.flatMap(d=>d.kind==="integration"?[d.provider]:[]),...C.flatMap(d=>d.provider==="discord"?["discord"]:[]),...Object.values(A).flatMap(d=>d.kind==="resource"&&d.source.provider!=="domino"?[d.source.provider]:[])];for(let d of K)if(!i.includes(d))throw new Error(`Declare the ${d} integration on this quest`);return Tt.parse({quest:a,evaluatorProtocol:ae,title:typeof t.title=="function"?t.title({settings:m}):t.title,presentation:t.presentation?.({settings:m})??{},fields:A,values:O,rewards:R,...C.length?{announcements:C}:{},humanReview:t.review?.({settings:m})?.enabled??!0,trigger:t.trigger,...h?{performance:P("performance",()=>H.parse({metrics:h.metrics,maxAgeMs:h.maxAgeMs}))}:{},integrations:i,...c.length>i.length?{integrationModules:c}:{},completion:o?o.kind==="progress"?{kind:o.kind,goal:o.goal,window:o.window,repeat:o.repeat}:o.kind==="streak"?o:o.kind==="keyed"&&o.across?{kind:o.kind,across:o.across}:{kind:o.kind}:{kind:"keyed"},visibility:t.visibility??"visible",profile:t.profile??{visible:!1},budgets:(t.budgets??[]).filter(d=>d.scope!=="author"),...w.length?{authorBudgets:w}:{},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},...y?{stations:y}:{},...k?{gallery:k}:{}})}return b("quest",{protocol:ae,key:a,describe:T,async evaluate(s){let h=t.settings.parse(s.settings),m=l?st.parse(s.tracker):null,O=tr.get(t.trigger),R=m&&O?Qe(O,m.record.data):null;if(R)return N.parse({kind:"reject",reason:`The record's data does not match the data schema this quest was built with: ${R.path} ${R.reason}`});let C=m;if(s.performance){if(!t.performance)throw new Error("Quest has no performance evaluator");let d=Lt.parse(s.performance),Q=U(L(t.performance.metrics),j().int().safe().nonnegative()).parse(d.metrics),v=await t.performance.evaluate({settings:h,member:s.member,tracker:C,metrics:Q,observedAt:d.observedAt});if(!v)throw new Error("Performance evaluator returned no decision");if(v.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 Yt(v),N.parse(v.kind==="accept"?{kind:"accept",rewards:d.rewards}:v.kind==="review"&&s.humanReview?{kind:"review",reason:v.reason,rewards:d.rewards}:{kind:"reject",reason:v.reason,...v.kind==="review"?{requestedReview:!0}:v.code===void 0?{}:{code:v.code}})}let g=t.evaluate?await t.evaluate({settings:h,member:s.member,input:s.input,tracker:C,action:s.action??null,eligibleAt:s.eligibleAt,calendar:s.calendar,now:s.now,review:s.review,trackers:Ue(s.trackers),wallet:s.wallet,images:s.images,...s.telegram?{telegram:s.telegram}:{},...Object.fromEntries(i.map(d=>[d,s[d]]))}):z.accept();if(!g)throw new Error("Evaluator returned no decision");if(Yt(g),g.kind==="review"&&!s.humanReview)return N.parse({kind:"reject",reason:g.reason,requestedReview:!0});(g.kind==="accept"||g.kind==="review")&&g.completionKey!==void 0&&o?.kind!=="keyed"&&s.diagnose?.({code:"completion-key-ignored",message:_r(o,g.completionKey)});let K={...s,settings:h,tracker:m,action:s.action??null};return N.parse(g.kind==="accept"||g.kind==="review"?{...g,rewards:g.rewards??s.rewards,...o?.kind==="keyed"||o?.kind==="progress"?{completionKey:o.kind==="progress"?o.distinct(K):g.completionKey??o.key(K)}:{}}:g)}})}}function _r(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 Fa=or(!1),Va=or(!0);export{qr as CapabilityError,Na as automatic,Ua as automaticFulfillment,Ta as badge,yr as balanceAtLeast,Oa as budget,da as calendar,Er as capabilityErrorCodes,vr as completed,Ia as content,Ae as cosmosDenomSchema,ir as cosmosNetworkSchema,la as count,S as customSource,z as decision,ca as defineBadge,wr as defineCampaign,Sr as defineDashboard,ua as defineEngagementReward,kr as defineGroup,wa as defineLeaderboard,ia as defineLedger,ga as defineOffer,Fa as defineQuest,Va as defineQuestType,pa as defineReferral,Wa as defineTieredReward,va as defineTracker,ya as discord,fa as earned,Za as evaluators,Ba as evidence,Cr as formatUnits,Pa as groupMembership,br as inGroup,ja as instruction,Ra as invoked,Re as isContractCall,je as isContractEvent,Ce as isEvmAddress,$e as isEvmChainId,G as isNftCollection,Te as isSolanaProgram,nr as keyed,Br as leaderboardTiesWarning,cr as limits,Da as manual,hr as maxWalletEventLogs,gr as maxWalletEventLookback,fr as maxWalletTransactionLookback,pr as maxWalletTransactions,Zr as once,dr as parseContractCall,mr as parseContractEvent,lr as parseContractFunction,ur as parseNftCollection,Ar as parseUnits,Ur as perStation,Aa as pointLedgers,La as points,Wr as progress,ha as questCompleted,xa as received,ma as rolling,Ca as settings,Ma as spent,Qa as staffHandover,jr as streak,za as swapped,ba as telegram,Ea as tiktok,D as trackerDataSchema,st as trackerTriggerContextSchema,Ka as untracked,qa as wallet,ka as x,Sa as youtube,sr as z};
|