@domino-sdk/relay 1.69.0 → 1.71.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/build.mjs +3 -0
  3. package/dist/{accounts-DD4gAOCe.d.ts → accounts-COLmXRbW.d.ts} +144 -13
  4. package/dist/{attempt-captures-CbuCmthd.d.ts → attempt-captures-CVl161qB.d.ts} +3 -2
  5. package/dist/authoring.d.ts +68 -25
  6. package/dist/authoring.js +15 -9
  7. package/dist/{automatic-outcomes-DE3vfi8g.d.ts → automatic-outcomes-5l68PGr1.d.ts} +2 -2
  8. package/dist/browser.d.ts +9 -9
  9. package/dist/browser.js +11 -9
  10. package/dist/{catalog-Cf3fHDNn.d.ts → catalog-BR3g-1H9.d.ts} +41 -2
  11. package/dist/{chunk-ME2KUAVJ.js → chunk-3KKRXN5E.js} +1 -1
  12. package/dist/{chunk-CQVKOD3B.js → chunk-74SMLZZ5.js} +723 -685
  13. package/dist/{chunk-CZ23KRVK.js → chunk-CVJTIVAP.js} +1 -1
  14. package/dist/{chunk-TCREFRPK.js → chunk-DDID5QX5.js} +153 -4
  15. package/dist/{chunk-WVK3G2J2.js → chunk-EMKYDGZ3.js} +1 -1
  16. package/dist/{chunk-2A3BJ262.js → chunk-FGZGL5PG.js} +1 -1
  17. package/dist/{chunk-GEVARKEV.js → chunk-GHBYWDEZ.js} +8 -1
  18. package/dist/{chunk-RKTMSTT7.js → chunk-HN7DE2UN.js} +2 -2
  19. package/dist/{chunk-LGGD7S5T.js → chunk-IDG2VPYG.js} +32 -6
  20. package/dist/{chunk-SWLW4VN3.js → chunk-KC4UB4ZX.js} +1 -1
  21. package/dist/{chunk-ODJGTFPY.js → chunk-KIRXE37T.js} +6 -6
  22. package/dist/{chunk-VAGGGB6B.js → chunk-MDSSIOBC.js} +58 -1
  23. package/dist/{chunk-BRROI4CH.js → chunk-OFSJYXGI.js} +12 -4
  24. package/dist/{chunk-LZXDYSUH.js → chunk-PYZSCFMJ.js} +4 -0
  25. package/dist/{chunk-UGM6DUB2.js → chunk-QMKTYPK6.js} +4 -3
  26. package/dist/{chunk-PO2ZDY27.js → chunk-TW4RABVS.js} +1 -1
  27. package/dist/{chunk-AZDZEQFK.js → chunk-UEVZ3TST.js} +29 -2
  28. package/dist/{chunk-DIXYVGXO.js → chunk-VFHLMNYV.js} +1 -1
  29. package/dist/{chunk-WNEQEDMU.js → chunk-W6DBNBMT.js} +2 -2
  30. package/dist/{client-6eSYOl8h.d.ts → client-B__hMWtK.d.ts} +104 -7
  31. package/dist/{dashboards-DCOAXL54.d.ts → dashboards-DXpjHnq-.d.ts} +3 -3
  32. package/dist/{deployments-BIfdCMd5.d.ts → deployments-CT2kQloT.d.ts} +199 -3
  33. package/dist/{identity-integration-BlfOn8rc.d.ts → identity-integration-ClX4oUAu.d.ts} +4 -4
  34. package/dist/index.d.ts +10 -10
  35. package/dist/index.js +7 -7
  36. package/dist/internal.d.ts +44 -26
  37. package/dist/internal.js +26 -50
  38. package/dist/{limits-Ctaeq23J.d.ts → limits-B7wbnWhd.d.ts} +1 -1
  39. package/dist/{offers-COqHGbHm.d.ts → offers-D4pyeY9b.d.ts} +2 -2
  40. package/dist/portal-proxy.d.ts +2 -2
  41. package/dist/portal-proxy.js +11 -10
  42. package/dist/react/index.d.ts +31 -12
  43. package/dist/react/index.js +116 -41
  44. package/dist/{reward-deliveries-DFhYGJdx.d.ts → reward-deliveries-HGpj1VFz.d.ts} +1 -1
  45. package/dist/runtime/authoring.js +1 -1
  46. package/dist/runtime/chunks/A7G5P76B.js +1 -0
  47. package/dist/runtime/manifest.json +3 -3
  48. package/dist/runtime/schema.js +1 -1
  49. package/dist/schema.d.ts +40 -16
  50. package/dist/schema.js +9 -7
  51. package/dist/server/index.d.ts +12 -12
  52. package/dist/server/index.js +944 -579
  53. package/dist/{sign-in-providers-C97mRNbG.d.ts → sign-in-providers-lbOXCF8N.d.ts} +2 -2
  54. package/dist/solana.d.ts +12 -12
  55. package/dist/solana.js +8 -8
  56. package/dist/{telegram-browser-gRMgGs7B.d.ts → station-check-in-qBiaftfE.d.ts} +89 -7
  57. package/dist/{submission-input-BD7nORuh.d.ts → submission-input-U4aIkJuT.d.ts} +2 -2
  58. package/dist/telegram.d.ts +7 -7
  59. package/dist/testing.d.ts +15 -11
  60. package/dist/testing.js +23 -12
  61. package/dist/{tracker-data-DQgX3FIc.d.ts → tracker-data-2BYXZjsN.d.ts} +3 -3
  62. package/dist/{transport-BLU8jrhg.d.ts → transport-fszraZPi.d.ts} +1736 -19
  63. package/dist/{wallet-CPAjrW4k.d.ts → wallet-BqswMAqZ.d.ts} +3 -1
  64. package/dist/{wallet-browser-BzPt_Qb5.d.ts → wallet-browser-B5r7u3xB.d.ts} +1 -1
  65. package/package.json +1 -1
  66. package/dist/runtime/chunks/HKAI5OQA.js +0 -1
@@ -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
- signInOptionsFrom
11
- } from "../chunk-TCREFRPK.js";
15
+ sendStationCheckIn,
16
+ signInOptionsFrom,
17
+ stationCheckInRetryable,
18
+ writeSessionItem
19
+ } from "../chunk-DDID5QX5.js";
12
20
  import {
13
21
  telegramMiniAppInitData
14
22
  } from "../chunk-FWLQ5XCS.js";
15
- import "../chunk-LGGD7S5T.js";
23
+ import "../chunk-IDG2VPYG.js";
16
24
  import {
17
25
  createRelayAction
18
26
  } from "../chunk-5RLIPTL7.js";
19
27
  import "../chunk-LDO5GP7G.js";
20
- import "../chunk-VAGGGB6B.js";
21
- import "../chunk-WVK3G2J2.js";
22
- import "../chunk-SWLW4VN3.js";
23
- import "../chunk-ME2KUAVJ.js";
28
+ import "../chunk-MDSSIOBC.js";
29
+ import "../chunk-EMKYDGZ3.js";
30
+ import "../chunk-KC4UB4ZX.js";
31
+ import "../chunk-3KKRXN5E.js";
24
32
  import {
25
33
  sessionMember
26
- } from "../chunk-PO2ZDY27.js";
27
- import "../chunk-2A3BJ262.js";
28
- import "../chunk-CQVKOD3B.js";
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
- try {
1069
- const value = JSON.parse(
1070
- window.sessionStorage.getItem(WALLET_SIGN_IN_KEY) ?? "null"
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
- try {
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
- try {
3211
- if (code && CODE.test(code)) {
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
- try {
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 = isRelayError(cause) && (cause.kind === "http" && cause.status !== void 0 && cause.status >= 400 && cause.status < 500 && cause.status !== 429 || cause.code === RelayErrorCode.InvalidInput);
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 useCallback10, useMemo as useMemo12 } from "react";
3447
+ import { useCallback as useCallback11, useMemo as useMemo13 } from "react";
3375
3448
  function useOffers() {
3376
3449
  const relay = useRelay();
3377
3450
  return useRelayQuery(
@@ -3386,11 +3459,12 @@ function useRedeemOffer() {
3386
3459
  { invalidates: [relayKeys.offers, relayKeys.balances] }
3387
3460
  );
3388
3461
  const { mutateAsync } = mutation;
3389
- const redeem = useCallback10(
3462
+ const redeem = useCallback11(
3463
+ // The mutation's error state carries the failure; redeem answers null for it.
3390
3464
  (offer) => mutateAsync(offer).catch(() => null),
3391
3465
  [mutateAsync]
3392
3466
  );
3393
- return useMemo12(
3467
+ return useMemo13(
3394
3468
  () => ({ ...mutation, redeem, retry: replay, busy: mutation.isPending }),
3395
3469
  [mutation, redeem, replay]
3396
3470
  );
@@ -3474,6 +3548,7 @@ export {
3474
3548
  useSignInOptions,
3475
3549
  useSignInWallets,
3476
3550
  useSignOut,
3551
+ useStationCheckIn,
3477
3552
  useTelegramAccount,
3478
3553
  useTieredRewards,
3479
3554
  useWalletDiscovery,
@@ -1,5 +1,5 @@
1
1
  import * as z from 'zod';
2
- import { T as TrackerSkipCode, S as SkipEnrollment } from './tracker-data-DQgX3FIc.js';
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{$a as dr,Ce as kt,Ci as kr,De as vt,Di as Pt,Ee as yt,Ei as Lt,Fe as E,Fi as Bt,Gd as at,Ge as bt,Gi as Dt,Hi as vr,Ia as Ce,Id as nt,If as ee,J as de,Ja as Ae,Ji as yr,K as me,Ka as or,Ke as x,Kf as D,L as ge,La as V,Lb as Fe,Li as Nt,M as fe,Mb as Qe,Mi as It,N as he,Na as xe,Ne as gr,Nf as $t,Ni as re,O as pe,Oa as sr,P as we,Pa as cr,Q as ke,Qa as $e,Qb as Ue,R as ve,Sb as We,Sd as ot,Ta as ir,Tb as Ze,Td as st,Th as Tt,Ua as Me,Ub as Ve,Ue as y,Va as ur,Vb as S,Vc as _,Ve as St,Vf as te,Wa as lr,Wc as Je,Wd as ct,We as $,Xc as H,Xd as it,Xf as Mt,Ya as ze,Yb as Ge,Yc as Ye,Ye as fr,Zb as G,Zg as Rt,_b as _e,a as A,ab as mr,b as oe,bc as He,be as ut,bj as Ot,c as T,ca as ye,d as Q,da as be,de as lt,dg as zt,ea as ar,ee as dt,eh as jt,f as le,fa as Se,fe as mt,ge as gt,ha as nr,hb as Re,he as ft,ia as Ee,ib as je,ka as L,kb as Te,lb as Pe,ma as Z,mb as Le,nb as Be,nd as Xe,nf as hr,ob as De,of as pr,pb as Ne,pf as wr,qd as et,qe as J,qf as Et,re as ht,rf as qt,rj as Kt,sa as qe,se as pt,tf as Ct,ub as B,ue as U,vb as Ie,vd as tt,vf as At,wb as Oe,xb as Ke,xe as Y,xf as xt,ye as X,zd as rt,ze as wt}from"./chunks/HKAI5OQA.js";import{Cb as R,Ec as P,Kb as ce,Pd as rr,fc as ie,ic as W,jc as ue,va as se,wc as F}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 br(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 Sr(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:"")}function Ut(e,r={}){let{trigger:t,completion:a,requires:n,performance:c,retryCooldownMs:i,completionCooldownMs:u,authorBudgets:l=[],stations:h}=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(h&&r.template)throw new Error("Reusable quest types cannot declare check-in stations: declare them on a quest written in code");if(h&&!ht(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 Er=["author"],qr=["author","messageAuthor"];function Wt(e){if(!He(e))return[];switch(e.kind){case"x-search":return Fe;case"discord-messages":return Er;case"discord-reactions":return qr;case"custom":return["author",...e.accounts??[]]}}var Qt=new Map;function Cr(e){let r=e.kind==="discord-messages"&&e.text?"messages-text":e.kind,t=Qt.get(r);return t||(t=B(r==="messages-text"?Be:r==="discord-messages"?Le:De),Qt.set(r,t)),t}function Zt(e){switch(e.kind){case"x-search":return;case"discord-messages":case"discord-reactions":return Cr(e);case"custom":return e.data}}function _t(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=_t(c,a);i&&e.addIssue({code:"custom",message:i,path:[...t,n]})}}function ta(e){return y("badge",A("Badge",le,e))}function ra(e){return y("ledger",A("Point ledger",jt,e))}function aa(e){let{target:r,ledger:t,...a}=e,n=Nt.parse({...a,qualifiedBy:e.qualifiedBy.key,balance:$(t)}),c=F(P(e.metrics),re.shape.target);return{key:n.key,describe:()=>n,score(i){let u=It.parse(i);return re.parse({target:r({metrics:c.parse(u.metrics)}),baseline:r({metrics:c.parse(u.baseline)})})}}}var xr=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 Xe.strict().parse({kind:"streak",...e})},na=e=>Je.brand().parse({kind:"count",count:e}),oa=(e,r={})=>H.brand().parse({kind:"calendar",period:e,...r}),sa=({days:e})=>H.brand().parse({kind:"rolling",durationMs:e*864e5}),ca=e=>({kind:"quest",quest:e}),$r=Kt.superRefine((e,r)=>{let t=_t(e.reward,"offers");t&&r.addIssue({code:"custom",message:t,path:["reward"]})});function ia(e){return y("offer",A("Offer",$r,e))}var Mr=Ot.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 ua(e){let{qualification:r,inviterGroup:t,milestones:a,bonuses:n,...c}=e,i=A("Referral",Mr,{...c,qualification:r.kind==="quest"?{kind:"quest",quest:r.quest.key}:r,...t?{inviterGroup:Q.parse(t.key)}:{},milestones:a?.map(({key:u,...l})=>({...l,id:x({key:u,...l})})),bonuses:n?.map(({key:u,ledger:l,quests:h,...s})=>({...s,id:x({key:u,...s}),balance:$(l),quests:h?.map(k=>k.key)}))});return y("referral",i)}function la(e={}){return{kind:"earned",...e}}var zr=Tt.superRefine((e,r)=>{for(let[t,a]of(e.settle?.prizes??[]).entries())ae(r,a.rewards,["settle","prizes",t,"rewards"],"leaderboard prizes")});function Rr(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 da(e){let{ledger:r,group:t,score:a,settle:n,...c}=e,i=n?.pool,u=A("Leaderboard",zr,{...c,...n?{settle:{...n,prizes:n.prizes??[],...i?{pool:{...i,...i.ledger===void 0?{}:{ledger:$(i.ledger)}}}:{}}}:{},balance:$(r),...t?{group:Q.parse(t.key)}:{},score:a?.kind==="earned"?{...a,quests:a.quests?.map(h=>h.key)}:a}),l=Rr(u);return l&&console.warn(l),y("leaderboard",u)}var ma={provider:"x",search:e=>Ve.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(!Vt(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)Qe.parse(i);return S.parse({kind:"custom",namespace:e,...n,data:B(W({body:a.body,metrics:ue(Object.fromEntries(c.map(i=>[i,R().int().safe().nonnegative().optional()]))).optional()})),content:{metrics:c}})}if(!Vt(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 Vt(e){return typeof e=="object"&&e!==null&&"_zod"in e}function ga(e){return y("tracker",A("Tracker",_e,e))}function jr(e={}){return Te.parse({kind:"discord-messages",...e.text?{text:!0}:{}})}function Tr(){return Pe.parse({kind:"discord-reactions"})}var fa={provider:"discord",grantRole:e=>Ne.parse({kind:"integration",provider:"discord",action:"grant-role",roleId:e}),postMessage(e){return dt.parse({provider:"discord",action:"post-message",...e})},messages:jr,reactions:Tr,roles(e={}){return U.parse({provider:"discord",resource:"role",assignable:e.assignable??!1})},channels(e={}){return U.parse({provider:"discord",resource:"channel",types:e.types??["text","announcement"],...e.postable?{postable:!0}:{}})}},ha={postMessage(e){return lt.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})}},pa={shorts(){return b(ge,{identities:["member"],content:{body:Pt,metrics:Lt}})}},wa={videos(){return b(fe,{identities:["member"],content:{body:Bt,metrics:Dt}})}};function Pr(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"&&Z(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"&&qe(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||!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 Lr(e){let{chain:r="solana",program:t,instruction:a,mint:n,minAmount:c,signer:i="wallet"}=e;if(r!=="solana"&&!(typeof r=="string"&&Z(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=Ue.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 ka={balances(e){let r=Pr(e),t=b(he,{identities:["wallet"],data:Ce});return S.parse({...t,balance:r})},programActivity(e){let r=Lr(e),t=b(pe,{identities:["wallet"],data:Ae});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:xe}),a={collection:r};return S.parse({...t,nfts:a})},stake(e={}){let{chain:r="solana",voteAccount:t}=e,a=We.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:Re});return S.parse({...n,stake:a.data})},programAccounts(e){let{chain:r="solana",idl:t,...a}=e,n=Ze.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:je});return S.parse({...c,programAccount:n.data})}},va=()=>({provider:"domino",resource:"point-ledger"});function p(e,r){return r}var ya={pointLedger(e){let r={...e,kind:"point-ledger",default:e.default?Q.parse(e.default.key):""};return p("point-ledger",St.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:U.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(!kt(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(!vt(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(!Me(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",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 W(e).strict()}};function Ht(e,r){let t=e.balanceChanges.find(a=>a.mint===r);return t?BigInt(t.delta):0n}function Sa(e,r){let t=Ht(e,r);return t>0n?t.toString():"0"}function Ea(e,r){let t=Ht(e,r);return t<0n?(-t).toString():"0"}function qa(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 Ca(e,r){return e.programs.includes(r)}function Aa(e,r){return e.instructions?.find(t=>t.name===r)?.args??null}var xa=e=>At(e.key,e.name),$a=e=>xt(e.key,e.title),Ma=(e,r)=>Et.parse({kind:"points",balance:$(e),amount:r}),za={text:(e={})=>({input:"text",constraints:gt.parse(e)}),url:(e={})=>({input:"url",constraints:ft.parse(e)}),photo:()=>"photo",quiz:()=>"quiz"};function Ra(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 Jt=new WeakMap,Yt=new WeakMap;function Xt(e,r){let{tracker:t,beneficiary:a="author",on:n,where:c,enrollment:i,since:u,historical:l,content:h}=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(!Ge(s))throw new Error('Tracker triggers need attributable records: declare customSource(namespace, { identities: ["wallet"] }) or other identity kinds');if(h&&!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=Wt(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=rt.parse({tracker:t.key,source:s.kind,on:h?"new-record":n??et(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!==(h?"claim":"staff")?{historical:l}:{},...h?{content:h}:{}}),v=Zt(s),N=v?Ke(v,q.where):null;if(N)throw new Error(N);let j={kind:"automatic",tracker:q};v&&Jt.set(j,v);let o=G(s);return o&&Yt.set(j,o.metrics),j}function ja(e){return e?Xt(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 Xt({...e,content:!0},"content")}function Br(e){let{key:r,cost:t,...a}=e,n={...a,id:x(e),cost:typeof t=="number"?t:{balance:$(t.ledger)}};return a.scope==="author"?st.parse(n):ot.parse(n)}var Pa=Br,Dr=(e=[])=>e.filter(r=>r.scope==="author"),er=(e,r={})=>({kind:"keyed",key:e,...r.across?{across:r.across}:{}}),Nr=()=>er(e=>{let r=e.action?.reference;if(!r)throw new Error("perStation() completes from a signed transaction whose memo names a station");return r}),Ir=e=>{let{distinct:r,...t}=e;return{...Ye.parse({kind:"progress",window:{kind:"lifetime"},...t}),distinct:r}},La=()=>({kind:"untracked"}),Ba=()=>({kind:"staff-handover"}),Da=()=>({kind:"automatic"});function Na(e){let{key:r,tiers:t,...a}=e,n=x(e),c=qt.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=>Ct.parse({kind:"tier",reward:c,tier:i})})}var Or=()=>({kind:"once"});function Kr(e={}){return{kind:"accept",...e}}function Fr(e){return{kind:"review",...e}}var M={accept:Kr,defer:e=>({kind:"defer",...e}),progress:e=>({kind:"progress",...e}),reject:e=>({kind:"reject",...e}),review:Fr};function Gt(e){let r=e.kind==="reject"&&e.code!==void 0?nt(e.code):null;if(r)throw new Error(r)}var Ia={quiz(e,r={}){let t=zt.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?M.accept():M.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"?M.review({reason:a.reason}):M.reject({reason:a.reason}):a.kind==="pass"?M.accept():M.reject({reason:a.reason})}}},Qr={once:Or,keyed:er,streak:xr,progress:Ir,perStation:Nr};function tr(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=>it.parse(o.provider)))],i=c.flatMap(o=>{let m=ct.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,h=t.completion,s=typeof h=="function"?h(Qr):h;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=Dr(t.budgets),q=t.stations?pt.parse(t.stations):void 0;if(Ut({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=Yt.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=wt.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 tt(t.trigger.kind==="automatic"?t.trigger.tracker?.where:void 0))if(!yt(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=bt(v,g),z=T("rewards",()=>$t.parse(typeof t.rewards=="function"?t.rewards({settings:g}):t.rewards)),C=T("announcements",()=>ie(mt).max(3,"A quest posts at most three announcements").parse((typeof t.announcements=="function"?t.announcements({settings:g}):t.announcements)??[])),f=t.trigger.kind==="automatic"&&t.trigger.tracker!==void 0;for(let d of C){let K=ut(d.text),w="segments"in K&&K.segments.some(ne=>ne.kind==="placeholder"&&ne.name==="author");if(!f&&w)throw new Error("An announcement names {author} only on a quest with an automatic tracker trigger");if(!f&&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 Mt.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?at.parse(o.tracker):null,I=Jt.get(t.trigger),z=g&&I?Ie(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=Rt.parse(o.performance),K=F(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 Gt(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 f=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:Oe(o.trackers),wallet:o.wallet,images:o.images,...o.telegram?{telegram:o.telegram}:{},...Object.fromEntries(i.map(d=>[d,o[d]]))}):M.accept();if(!f)throw new Error("Evaluator returned no decision");if(Gt(f),f.kind==="review"&&!o.humanReview)return D.parse({kind:"reject",reason:f.reason,requestedReview:!0});(f.kind==="accept"||f.kind==="review")&&f.completionKey!==void 0&&s?.kind!=="keyed"&&o.diagnose?.({code:"completion-key-ignored",message:Ur(s,f.completionKey)});let O={...o,settings:m,tracker:g,action:o.action??null};return D.parse(f.kind==="accept"||f.kind==="review"?{...f,rewards:f.rewards??o.rewards,...s?.kind==="keyed"||s?.kind==="progress"?{completionKey:s.kind==="progress"?s.distinct(O):f.completionKey??s.key(O)}:{}}:f)}})}}function Ur(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 Oa=tr(!1),Ka=tr(!0);export{yr as CapabilityError,ja as automatic,Da as automaticFulfillment,xa as badge,pr as balanceAtLeast,Pa as budget,oa as calendar,vr as capabilityErrorCodes,hr as completed,Ta as content,Ee as cosmosDenomSchema,nr as cosmosNetworkSchema,na as count,b as customSource,M as decision,ta as defineBadge,gr as defineCampaign,kr as defineDashboard,aa as defineEngagementReward,fr as defineGroup,da as defineLeaderboard,ra as defineLedger,ia as defineOffer,Oa as defineQuest,Ka as defineQuestType,ua as defineReferral,Na as defineTieredReward,ga as defineTracker,fa as discord,la as earned,Ia as evaluators,za as evidence,Sr as formatUnits,$a as groupMembership,wr as inGroup,Aa as instruction,Ca as invoked,$e as isContractCall,Me as isContractEvent,qe as isEvmChainId,V as isNftCollection,ze as isSolanaProgram,er as keyed,Rr as leaderboardTiesWarning,ar as limits,Ra as manual,ur as maxWalletEventLogs,lr as maxWalletEventLookback,mr as maxWalletTransactionLookback,dr as maxWalletTransactions,Or as once,cr as parseContractCall,ir as parseContractEvent,sr as parseContractFunction,or as parseNftCollection,br as parseUnits,Nr as perStation,va as pointLedgers,Ma as points,Ir as progress,ca as questCompleted,Sa as received,sa as rolling,ya as settings,Ea as spent,Ba as staffHandover,xr as streak,qa as swapped,ha as telegram,wa as tiktok,B as trackerDataSchema,at as trackerTriggerContextSchema,La as untracked,ka as wallet,ma as x,pa as youtube,rr 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};