@domino-sdk/relay 1.0.0-next.9 → 1.1.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/README.md +1 -1
- package/dist/activity-B8k9Sa_a.d.ts +9112 -0
- package/dist/authoring.d.ts +1053 -259
- package/dist/authoring.js +478 -277
- package/dist/automatic-outcomes-B1xrETxm.d.ts +758 -0
- package/dist/avatar.d.ts +2 -2
- package/dist/browser-J7tUpXxy.d.ts +4154 -0
- package/dist/browser.d.ts +11 -2613
- package/dist/browser.js +8 -6
- package/dist/{integrations-Ba5TtqTv.d.ts → capability-error-DNMwKmlL.d.ts} +124 -76
- package/dist/{chunk-PHU5VDLR.js → chunk-36HTX2BM.js} +389 -169
- package/dist/chunk-6QJ3LADK.js +112 -0
- package/dist/{chunk-4LBUTHD6.js → chunk-BGGKNIRP.js} +1 -1
- package/dist/chunk-EYH5RDIE.js +496 -0
- package/dist/chunk-GQKYAQM6.js +84 -0
- package/dist/chunk-GUP7YRR4.js +42 -0
- package/dist/{chunk-X2F2RAR3.js → chunk-GZ6FJAXN.js} +380 -128
- package/dist/chunk-JON5SESL.js +2986 -0
- package/dist/chunk-MC6V6VMG.js +49 -0
- package/dist/chunk-NPGENI7K.js +37 -0
- package/dist/chunk-VFHHLN6A.js +284 -0
- package/dist/chunk-WJSSJ7AF.js +151 -0
- package/dist/{chunk-7Q4BGGT6.js → chunk-XFMSUPNS.js} +1 -1
- package/dist/{chunk-P6FK43GG.js → chunk-ZVIRG24J.js} +145 -42
- package/dist/{client-CT4-S5vc.d.ts → client-XiuFnug_.d.ts} +2161 -615
- package/dist/{submission-input-0OOGaq8c.d.ts → groups-Ck-OxzjD.d.ts} +916 -1139
- package/dist/identity-integration-GxAHdKR2.d.ts +58 -0
- package/dist/images-Dv-P5VBw.d.ts +234 -0
- package/dist/index.d.ts +13 -9
- package/dist/index.js +17 -6
- package/dist/internal.d.ts +82 -44
- package/dist/internal.js +43 -89
- package/dist/offers-Cy-e4o5x.d.ts +431 -0
- package/dist/{pages-D3titw5B.d.ts → outcomes-kVB-Juzs.d.ts} +2157 -1448
- package/dist/pages-BBYD21IE.d.ts +359 -0
- package/dist/participant-rewards-3duLb8YJ.d.ts +668 -0
- package/dist/portal-proxy.js +22 -4
- package/dist/{profiles-DDMFBRKe.d.ts → profiles-D2aFcOxu.d.ts} +15 -15
- package/dist/react/index.d.ts +3038 -1029
- package/dist/react/index.js +1627 -779
- package/dist/request-error-DWduJCGV.d.ts +62 -0
- package/dist/schema-DfJzH2ci.d.ts +5644 -0
- package/dist/schema.d.ts +15 -4168
- package/dist/schema.js +310 -81
- package/dist/server/index.d.ts +81722 -0
- package/dist/server/index.js +2569 -0
- package/dist/{streaks-CwGReWGt.d.ts → streaks-CWyq8Px5.d.ts} +2 -4
- package/dist/submission-input-BZkm6ohU.d.ts +290 -0
- package/dist/vite.d.ts +1 -1
- package/dist/vite.js +1 -0
- package/dist/{wallet-BGOfFkG9.d.ts → wallet-YssWxGg8.d.ts} +35 -38
- package/package.json +8 -2
- package/dist/chunk-QR7ZA2BJ.js +0 -257
- package/dist/chunk-YYD4QUBO.js +0 -2348
- package/dist/chunk-ZWY3R6B3.js +0 -26
- package/dist/collection-BGneJ6Bk.d.ts +0 -114
- package/dist/images-BTgk6OmC.d.ts +0 -1564
- package/dist/point-ledgers-iS00Z_v0.d.ts +0 -37
- package/dist/schema-Di3aLSiK.d.ts +0 -3532
package/dist/authoring.js
CHANGED
|
@@ -3,36 +3,65 @@ import {
|
|
|
3
3
|
parseUnits
|
|
4
4
|
} from "./chunk-V7UKZLHA.js";
|
|
5
5
|
import {
|
|
6
|
-
|
|
6
|
+
CapabilityError,
|
|
7
|
+
capabilityErrorCodes
|
|
8
|
+
} from "./chunk-MC6V6VMG.js";
|
|
9
|
+
import {
|
|
10
|
+
sourceDataSchema,
|
|
11
|
+
sourceRoles,
|
|
12
|
+
validateQuestShape
|
|
13
|
+
} from "./chunk-GQKYAQM6.js";
|
|
14
|
+
import {
|
|
15
|
+
cosmosDenomSchema,
|
|
16
|
+
cosmosNetworkSchema,
|
|
17
|
+
defineOffer,
|
|
7
18
|
engagementDefinitionSchema,
|
|
8
19
|
engagementScoreInputSchema,
|
|
9
20
|
engagementScoreSchema,
|
|
10
21
|
isEvmChainId,
|
|
11
22
|
leaderboardAuthoringSchema,
|
|
23
|
+
pointLedgerDeclarationSchema,
|
|
12
24
|
referralAuthoringSchema
|
|
13
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-36HTX2BM.js";
|
|
26
|
+
import "./chunk-NPGENI7K.js";
|
|
14
27
|
import {
|
|
15
|
-
|
|
28
|
+
authoringKey,
|
|
29
|
+
balanceAtLeast,
|
|
16
30
|
budgetSchema,
|
|
31
|
+
completed,
|
|
32
|
+
contentMetricNameSchema,
|
|
17
33
|
contentPerformancePolicySchema,
|
|
18
34
|
contentPerformanceSnapshotSchema,
|
|
19
|
-
|
|
35
|
+
counterGoalSchema,
|
|
36
|
+
counterPolicySchema,
|
|
37
|
+
counterWindowSchema,
|
|
20
38
|
customSourceSchema,
|
|
21
39
|
decisionSchema,
|
|
22
40
|
defaultTriggerMode,
|
|
41
|
+
defineCampaign,
|
|
42
|
+
defineGroup,
|
|
43
|
+
discordMessagesSourceSchema,
|
|
44
|
+
discordReactionsSourceSchema,
|
|
45
|
+
discordRewardSchema,
|
|
46
|
+
evaluatorIntegrationProviderSchema,
|
|
47
|
+
evaluatorProtocol,
|
|
23
48
|
identifier,
|
|
24
|
-
|
|
49
|
+
inGroup,
|
|
50
|
+
ledgerKey,
|
|
51
|
+
ledgerSettingSchema,
|
|
25
52
|
parseSettings,
|
|
26
53
|
pointsRewardSchema,
|
|
27
54
|
questDescriptionSchema,
|
|
28
55
|
quizAnswersSchema,
|
|
29
56
|
quizContentSchema,
|
|
57
|
+
resourceHandle,
|
|
30
58
|
resourceSourceSchema,
|
|
31
59
|
rewardBundleSchema,
|
|
32
60
|
schemaCheckedReader,
|
|
33
61
|
settingFieldSchema,
|
|
34
62
|
settingInstant,
|
|
35
63
|
settingResourceId,
|
|
64
|
+
sourceContent,
|
|
36
65
|
sourceIdentities,
|
|
37
66
|
streakPolicySchema,
|
|
38
67
|
textOptionsSchema,
|
|
@@ -46,42 +75,20 @@ import {
|
|
|
46
75
|
urlOptionsSchema,
|
|
47
76
|
whereSchemaIssue,
|
|
48
77
|
whereSettings,
|
|
49
|
-
xAccountRoles,
|
|
50
78
|
xSearchSourceSchema
|
|
51
|
-
} from "./chunk-
|
|
79
|
+
} from "./chunk-JON5SESL.js";
|
|
52
80
|
|
|
53
81
|
// src/builders.ts
|
|
54
82
|
import { z } from "zod";
|
|
55
|
-
function
|
|
56
|
-
|
|
57
|
-
throw new Error("Content quests require an X tracker");
|
|
58
|
-
}
|
|
59
|
-
return {
|
|
60
|
-
kind: "automatic",
|
|
61
|
-
content: contentPolicySchema.parse({
|
|
62
|
-
tracker: tracker.key,
|
|
63
|
-
window: tracker.window,
|
|
64
|
-
...policy
|
|
65
|
-
})
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
function perContent() {
|
|
69
|
-
return {
|
|
70
|
-
kind: "keyed",
|
|
71
|
-
perContent: true,
|
|
72
|
-
key: (ctx) => {
|
|
73
|
-
if (!ctx.content) {
|
|
74
|
-
throw new Error("perContent requires an admitted content item");
|
|
75
|
-
}
|
|
76
|
-
return ctx.content.completionKey;
|
|
77
|
-
}
|
|
78
|
-
};
|
|
83
|
+
function defineLedger(input) {
|
|
84
|
+
return resourceHandle("ledger", pointLedgerDeclarationSchema.parse(input));
|
|
79
85
|
}
|
|
80
86
|
function defineEngagementReward(input) {
|
|
81
|
-
const { target, ...config } = input;
|
|
87
|
+
const { target, ledger, ...config } = input;
|
|
82
88
|
const definition = engagementDefinitionSchema.parse({
|
|
83
89
|
...config,
|
|
84
|
-
qualifiedBy:
|
|
90
|
+
qualifiedBy: input.qualifiedBy.key,
|
|
91
|
+
balance: ledgerKey(ledger)
|
|
85
92
|
});
|
|
86
93
|
const selected = z.record(
|
|
87
94
|
z.enum(input.metrics),
|
|
@@ -99,29 +106,99 @@ function defineEngagementReward(input) {
|
|
|
99
106
|
}
|
|
100
107
|
};
|
|
101
108
|
}
|
|
102
|
-
var streak = (options) =>
|
|
109
|
+
var streak = (options) => {
|
|
110
|
+
if ("timeZone" in options) {
|
|
111
|
+
throw new Error(
|
|
112
|
+
"streak() no longer takes a timeZone. Set the project timezone with calendar.timeZone in relay.json or in Console settings."
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
return streakPolicySchema.strict().parse({ kind: "streak", ...options });
|
|
116
|
+
};
|
|
117
|
+
var count = (count2) => counterGoalSchema.brand().parse({ kind: "count", count: count2 });
|
|
118
|
+
var calendar = (period, options = {}) => counterWindowSchema.brand().parse({ kind: "calendar", period, ...options });
|
|
119
|
+
var rolling = ({ days }) => counterWindowSchema.brand().parse({ kind: "rolling", durationMs: days * 864e5 });
|
|
120
|
+
var questCompleted = (quest) => ({
|
|
121
|
+
kind: "quest",
|
|
122
|
+
quest
|
|
123
|
+
});
|
|
103
124
|
function defineReferral(input) {
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
...
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
125
|
+
const { qualification, inviterGroup, milestones, bonuses, ...properties } = input;
|
|
126
|
+
const definition = referralAuthoringSchema.parse({
|
|
127
|
+
...properties,
|
|
128
|
+
qualification: qualification.kind === "quest" ? { kind: "quest", quest: qualification.quest.key } : qualification,
|
|
129
|
+
...inviterGroup ? { inviterGroup: identifier.parse(inviterGroup.key) } : {},
|
|
130
|
+
milestones: milestones?.map(({ key, ...rule }) => ({
|
|
131
|
+
...rule,
|
|
132
|
+
id: authoringKey({ key, ...rule })
|
|
133
|
+
})),
|
|
134
|
+
bonuses: bonuses?.map(({ key, ledger, quests, ...rule }) => ({
|
|
135
|
+
...rule,
|
|
136
|
+
id: authoringKey({ key, ...rule }),
|
|
137
|
+
balance: ledgerKey(ledger),
|
|
138
|
+
quests: quests?.map((quest) => quest.key)
|
|
139
|
+
}))
|
|
140
|
+
});
|
|
141
|
+
return resourceHandle("referral", definition);
|
|
142
|
+
}
|
|
143
|
+
function earned(options = {}) {
|
|
144
|
+
return { kind: "earned", ...options };
|
|
110
145
|
}
|
|
111
146
|
function defineLeaderboard(input) {
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
...
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
147
|
+
const { ledger, group, score, ...properties } = input;
|
|
148
|
+
const definition = leaderboardAuthoringSchema.parse({
|
|
149
|
+
...properties,
|
|
150
|
+
balance: ledgerKey(ledger),
|
|
151
|
+
...group ? { group: identifier.parse(group.key) } : {},
|
|
152
|
+
score: score?.kind === "earned" ? { ...score, quests: score.quests?.map((quest) => quest.key) } : score
|
|
153
|
+
});
|
|
154
|
+
return resourceHandle("leaderboard", definition);
|
|
118
155
|
}
|
|
119
156
|
var x = {
|
|
120
|
-
|
|
157
|
+
provider: "x",
|
|
158
|
+
/**
|
|
159
|
+
* Posts matching an X search. Each record's `data` is the provider's post payload. Its content
|
|
160
|
+
* is the post's normalized body (`XContentBody`), measured by the six X counters, so `content()`
|
|
161
|
+
* quests can use it.
|
|
162
|
+
*/
|
|
121
163
|
search: (input) => xSearchSourceSchema.parse({ kind: "x-search", ...input })
|
|
122
164
|
};
|
|
123
165
|
function customSource(namespace, options) {
|
|
124
|
-
const { data, ...rest } = options ?? {};
|
|
166
|
+
const { data, content: content2, ...rest } = options ?? {};
|
|
167
|
+
if (content2 !== void 0) {
|
|
168
|
+
if (data !== void 0) {
|
|
169
|
+
throw new Error(
|
|
170
|
+
`customSource("${namespace}") takes data or content, not both: a content source's records carry { body, metrics }`
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
if (!isZodSchema(content2.body)) {
|
|
174
|
+
throw new Error(
|
|
175
|
+
`customSource("${namespace}") needs a content body schema: customSource(namespace, { content: { body: z.object({ ... }), metrics: ["likes"] } })`
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
const metrics = [...content2.metrics ?? []];
|
|
179
|
+
for (const metric of metrics) {
|
|
180
|
+
contentMetricNameSchema.parse(metric);
|
|
181
|
+
}
|
|
182
|
+
return customSourceSchema.parse({
|
|
183
|
+
kind: "custom",
|
|
184
|
+
namespace,
|
|
185
|
+
...rest,
|
|
186
|
+
data: trackerDataSchema(
|
|
187
|
+
z.object({
|
|
188
|
+
body: content2.body,
|
|
189
|
+
metrics: z.strictObject(
|
|
190
|
+
Object.fromEntries(
|
|
191
|
+
metrics.map((metric) => [
|
|
192
|
+
metric,
|
|
193
|
+
z.number().int().safe().nonnegative().optional()
|
|
194
|
+
])
|
|
195
|
+
)
|
|
196
|
+
).optional()
|
|
197
|
+
})
|
|
198
|
+
),
|
|
199
|
+
content: { metrics }
|
|
200
|
+
});
|
|
201
|
+
}
|
|
125
202
|
if (!isZodSchema(data)) {
|
|
126
203
|
throw new Error(
|
|
127
204
|
`customSource("${namespace}") needs a data schema: customSource(namespace, { data: z.object({ ... }) }) describes each record's data`
|
|
@@ -138,9 +215,30 @@ function isZodSchema(value) {
|
|
|
138
215
|
return typeof value === "object" && value !== null && "_zod" in value;
|
|
139
216
|
}
|
|
140
217
|
function defineTracker(input) {
|
|
141
|
-
return
|
|
218
|
+
return resourceHandle(
|
|
219
|
+
"tracker",
|
|
220
|
+
trackerDefinitionSchema.parse(input)
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
function messages(options = {}) {
|
|
224
|
+
return discordMessagesSourceSchema.parse({
|
|
225
|
+
kind: "discord-messages",
|
|
226
|
+
...options.text ? { text: true } : {}
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
function reactions() {
|
|
230
|
+
return discordReactionsSourceSchema.parse({ kind: "discord-reactions" });
|
|
142
231
|
}
|
|
143
232
|
var discord = {
|
|
233
|
+
provider: "discord",
|
|
234
|
+
grantRole: (roleId) => discordRewardSchema.parse({
|
|
235
|
+
kind: "integration",
|
|
236
|
+
provider: "discord",
|
|
237
|
+
action: "grant-role",
|
|
238
|
+
roleId
|
|
239
|
+
}),
|
|
240
|
+
messages,
|
|
241
|
+
reactions,
|
|
144
242
|
roles(options = {}) {
|
|
145
243
|
return resourceSourceSchema.parse({
|
|
146
244
|
provider: "discord",
|
|
@@ -168,11 +266,11 @@ var settings = {
|
|
|
168
266
|
const field = {
|
|
169
267
|
...options,
|
|
170
268
|
kind: "point-ledger",
|
|
171
|
-
default: identifier.parse(options.default)
|
|
269
|
+
default: options.default ? identifier.parse(options.default.key) : ""
|
|
172
270
|
};
|
|
173
271
|
return setting(
|
|
174
272
|
"point-ledger",
|
|
175
|
-
|
|
273
|
+
ledgerSettingSchema.prefault(field.default).meta(field)
|
|
176
274
|
);
|
|
177
275
|
},
|
|
178
276
|
datetime(options) {
|
|
@@ -245,12 +343,10 @@ var settings = {
|
|
|
245
343
|
// src/authoring.ts
|
|
246
344
|
import { z as z2 } from "zod";
|
|
247
345
|
import { z as z3 } from "zod";
|
|
248
|
-
var points = (
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
action: "grant-role",
|
|
253
|
-
roleId
|
|
346
|
+
var points = (ledger, amount) => pointsRewardSchema.parse({
|
|
347
|
+
kind: "points",
|
|
348
|
+
balance: ledgerKey(ledger),
|
|
349
|
+
amount
|
|
254
350
|
});
|
|
255
351
|
var evidence = {
|
|
256
352
|
text: (options = {}) => ({
|
|
@@ -280,69 +376,128 @@ function manual(options) {
|
|
|
280
376
|
};
|
|
281
377
|
}
|
|
282
378
|
var triggerDataSchemas = /* @__PURE__ */ new WeakMap();
|
|
379
|
+
var triggerContentMetrics = /* @__PURE__ */ new WeakMap();
|
|
380
|
+
function trackerTrigger(input, constructor) {
|
|
381
|
+
const {
|
|
382
|
+
tracker,
|
|
383
|
+
beneficiary = "author",
|
|
384
|
+
on,
|
|
385
|
+
where,
|
|
386
|
+
enrollment,
|
|
387
|
+
since,
|
|
388
|
+
historical,
|
|
389
|
+
content: content2
|
|
390
|
+
} = input;
|
|
391
|
+
if (!tracker?.source) {
|
|
392
|
+
throw new Error(
|
|
393
|
+
constructor === "automatic" ? "automatic() takes no argument, or { tracker } with a tracker handle from defineTracker" : "content() takes { tracker } with a tracker handle from defineTracker"
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
const { source } = tracker;
|
|
397
|
+
if (!sourceIdentities(source)) {
|
|
398
|
+
throw new Error(
|
|
399
|
+
'Tracker triggers need attributable records: declare customSource(namespace, { identities: ["wallet"] }) or other identity kinds'
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
if (content2 && !sourceContent(source)) {
|
|
403
|
+
throw new Error(
|
|
404
|
+
`content() needs a tracker whose source has content: x.search(), or customSource(namespace, { content: { body, metrics } }). Tracker "${tracker.key}" has none; use automatic({ tracker }) instead.`
|
|
405
|
+
);
|
|
406
|
+
}
|
|
407
|
+
if (since === "enrollment" && enrollment !== "required") {
|
|
408
|
+
throw new Error(
|
|
409
|
+
`${constructor}() counts from enrollment only on a quest that requires it: add enrollment: "required"`
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
const roles = sourceRoles(source);
|
|
413
|
+
if (!roles.includes(beneficiary)) {
|
|
414
|
+
throw new Error(
|
|
415
|
+
source.kind === "custom" ? `Tracker "${tracker.key}" has no "${beneficiary}" account: declare it in customSource(namespace, { accounts: ["${beneficiary}"] })` : `Tracker "${tracker.key}" pays ${roles.map((role) => `"${role}"`).join(" or ")}, not "${beneficiary}"`
|
|
416
|
+
);
|
|
417
|
+
}
|
|
418
|
+
const policy = trackerTriggerPolicySchema.parse({
|
|
419
|
+
tracker: tracker.key,
|
|
420
|
+
source: source.kind,
|
|
421
|
+
// A content item is decided by its first observation; later observations run its stage.
|
|
422
|
+
on: content2 ? "new-record" : on ?? defaultTriggerMode(source.kind),
|
|
423
|
+
...where ? { where } : {},
|
|
424
|
+
beneficiary,
|
|
425
|
+
// Defaults are left out too: "none", "activation", and "staff" ("claim" on content).
|
|
426
|
+
...enrollment === "required" ? { enrollment } : {},
|
|
427
|
+
...since && since !== "activation" ? { since } : {},
|
|
428
|
+
...historical && historical !== (content2 ? "claim" : "staff") ? { historical } : {},
|
|
429
|
+
...content2 ? { content: content2 } : {}
|
|
430
|
+
});
|
|
431
|
+
const schema = sourceDataSchema(source);
|
|
432
|
+
const issue = schema ? whereSchemaIssue(schema, policy.where) : null;
|
|
433
|
+
if (issue) {
|
|
434
|
+
throw new Error(issue);
|
|
435
|
+
}
|
|
436
|
+
const trigger = { kind: "automatic", tracker: policy };
|
|
437
|
+
if (schema) {
|
|
438
|
+
triggerDataSchemas.set(trigger, schema);
|
|
439
|
+
}
|
|
440
|
+
const declared = sourceContent(source);
|
|
441
|
+
if (declared) {
|
|
442
|
+
triggerContentMetrics.set(trigger, declared.metrics);
|
|
443
|
+
}
|
|
444
|
+
return trigger;
|
|
445
|
+
}
|
|
283
446
|
function automatic(input) {
|
|
284
447
|
if (!input) {
|
|
285
448
|
return { kind: "automatic" };
|
|
286
449
|
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
}
|
|
295
|
-
if (!sourceIdentities(source)) {
|
|
296
|
-
throw new Error(
|
|
297
|
-
'Tracker triggers need attributable records: declare customSource(namespace, { identities: ["wallet"] }) or other identity kinds'
|
|
298
|
-
);
|
|
299
|
-
}
|
|
300
|
-
if (source.kind === "custom" && beneficiary !== "author" && !source.accounts?.includes(beneficiary)) {
|
|
301
|
-
throw new Error(
|
|
302
|
-
`Tracker "${tracker.key}" has no "${beneficiary}" account: declare it in customSource(namespace, { accounts: ["${beneficiary}"] })`
|
|
303
|
-
);
|
|
304
|
-
}
|
|
305
|
-
const policy = trackerTriggerPolicySchema.parse({
|
|
306
|
-
tracker: tracker.key,
|
|
307
|
-
source: source.kind,
|
|
308
|
-
// The source's default mode is left out, so default quests keep the policy shape
|
|
309
|
-
// earlier SDKs and servers read.
|
|
310
|
-
...on && on !== defaultTriggerMode(source.kind) ? { on } : {},
|
|
311
|
-
...where ? { where } : {},
|
|
312
|
-
beneficiary
|
|
313
|
-
});
|
|
314
|
-
const issue = source.kind === "custom" && source.data ? whereSchemaIssue(source.data, policy.where) : null;
|
|
315
|
-
if (issue) {
|
|
316
|
-
throw new Error(issue);
|
|
317
|
-
}
|
|
318
|
-
const trigger = { kind: "automatic", tracker: policy };
|
|
319
|
-
if (source.kind === "custom" && source.data) {
|
|
320
|
-
triggerDataSchemas.set(trigger, source.data);
|
|
321
|
-
}
|
|
322
|
-
return trigger;
|
|
450
|
+
return trackerTrigger(input, "automatic");
|
|
451
|
+
}
|
|
452
|
+
function content(input) {
|
|
453
|
+
if (input && typeof input === "object" && "source" in input && "key" in input && !("tracker" in input)) {
|
|
454
|
+
throw new Error(
|
|
455
|
+
"content() takes { tracker }: write content({ tracker: posts }) instead of content(posts)"
|
|
456
|
+
);
|
|
323
457
|
}
|
|
324
|
-
return {
|
|
458
|
+
return trackerTrigger({ ...input, content: true }, "content");
|
|
325
459
|
}
|
|
326
|
-
var budget = (definition) =>
|
|
460
|
+
var budget = (definition) => {
|
|
461
|
+
const { key: _, cost, ...properties } = definition;
|
|
462
|
+
return budgetSchema.parse({
|
|
463
|
+
...properties,
|
|
464
|
+
id: authoringKey(definition),
|
|
465
|
+
cost: typeof cost === "number" ? cost : { balance: ledgerKey(cost.ledger) }
|
|
466
|
+
});
|
|
467
|
+
};
|
|
327
468
|
var keyed = (key) => ({
|
|
328
469
|
kind: "keyed",
|
|
329
470
|
key
|
|
330
471
|
});
|
|
331
|
-
var
|
|
332
|
-
|
|
333
|
-
|
|
472
|
+
var progress = (definition) => {
|
|
473
|
+
const { distinct, ...policy } = definition;
|
|
474
|
+
return {
|
|
475
|
+
...counterPolicySchema.parse({
|
|
476
|
+
kind: "progress",
|
|
477
|
+
window: { kind: "lifetime" },
|
|
478
|
+
...policy
|
|
479
|
+
}),
|
|
480
|
+
distinct
|
|
481
|
+
};
|
|
482
|
+
};
|
|
334
483
|
var untracked = () => ({ kind: "untracked" });
|
|
335
484
|
var staffHandover = () => ({ kind: "staff-handover" });
|
|
485
|
+
var automaticFulfillment = () => ({ kind: "automatic" });
|
|
336
486
|
function defineTieredReward(input) {
|
|
337
|
-
const { key: _,
|
|
487
|
+
const { key: _, tiers, ...properties } = input;
|
|
338
488
|
const key = authoringKey(input);
|
|
339
|
-
const reward = tieredRewardDefinitionSchema.parse({
|
|
340
|
-
|
|
489
|
+
const reward = tieredRewardDefinitionSchema.parse({
|
|
490
|
+
id: key,
|
|
491
|
+
...properties,
|
|
492
|
+
tiers: tiers.map(({ key: key2, ...tier }) => ({
|
|
493
|
+
...tier,
|
|
494
|
+
id: authoringKey({ key: key2, ...tier })
|
|
495
|
+
}))
|
|
496
|
+
});
|
|
497
|
+
return resourceHandle("tiered-reward", {
|
|
341
498
|
key: reward.id,
|
|
342
|
-
/** @deprecated Authoring key alias. Use key. */
|
|
343
|
-
id: reward.id,
|
|
344
499
|
tier: (tier) => tierRewardSchema.parse({ kind: "tier", reward, tier })
|
|
345
|
-
};
|
|
500
|
+
});
|
|
346
501
|
}
|
|
347
502
|
var once = () => ({ kind: "once" });
|
|
348
503
|
function accept(options = {}) {
|
|
@@ -353,6 +508,11 @@ function review(options) {
|
|
|
353
508
|
}
|
|
354
509
|
var decision = {
|
|
355
510
|
accept,
|
|
511
|
+
defer: (options) => ({ kind: "defer", ...options }),
|
|
512
|
+
progress: (options) => ({
|
|
513
|
+
kind: "progress",
|
|
514
|
+
...options
|
|
515
|
+
}),
|
|
356
516
|
reject: (options) => ({
|
|
357
517
|
kind: "reject",
|
|
358
518
|
...options
|
|
@@ -386,221 +546,262 @@ var evaluators = {
|
|
|
386
546
|
};
|
|
387
547
|
}
|
|
388
548
|
};
|
|
389
|
-
function
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
549
|
+
function questBuilder(template) {
|
|
550
|
+
return function defineQuest2(definition) {
|
|
551
|
+
const key = authoringKey(definition);
|
|
552
|
+
const integrations = [
|
|
553
|
+
...new Set(
|
|
554
|
+
(definition.integrations ?? []).map(
|
|
555
|
+
(module) => evaluatorIntegrationProviderSchema.parse(module.provider)
|
|
556
|
+
)
|
|
557
|
+
)
|
|
558
|
+
];
|
|
559
|
+
const contentTrigger = definition.trigger.kind === "automatic" && definition.trigger.tracker?.content === true;
|
|
560
|
+
const trackerTrigger2 = definition.trigger.kind === "automatic" && definition.trigger.tracker !== void 0;
|
|
561
|
+
const completion = definition.completion;
|
|
562
|
+
if (contentTrigger && completion !== void 0) {
|
|
563
|
+
throw new Error(
|
|
564
|
+
"A content quest completes once per content item: remove its completion"
|
|
565
|
+
);
|
|
566
|
+
}
|
|
567
|
+
if (!contentTrigger && completion === void 0) {
|
|
568
|
+
throw new Error(
|
|
569
|
+
"A quest needs a completion, such as once(), keyed(...), streak(...) or progress(...)"
|
|
570
|
+
);
|
|
571
|
+
}
|
|
572
|
+
validateQuestShape(
|
|
573
|
+
{
|
|
574
|
+
trigger: definition.trigger,
|
|
575
|
+
completion: completion ?? { kind: "keyed" },
|
|
576
|
+
requires: definition.requires ?? [],
|
|
577
|
+
performance: definition.performance ? contentPerformancePolicySchema.parse({
|
|
578
|
+
metrics: definition.performance.metrics,
|
|
579
|
+
maxAgeMs: definition.performance.maxAgeMs
|
|
580
|
+
}) : void 0
|
|
581
|
+
},
|
|
582
|
+
{ template }
|
|
411
583
|
);
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
const field = settingFieldSchema.safeParse(schema.meta());
|
|
419
|
-
if (!field.success) {
|
|
584
|
+
if (definition.performance) {
|
|
585
|
+
const declared = triggerContentMetrics.get(definition.trigger) ?? [];
|
|
586
|
+
const unknown = definition.performance.metrics.filter(
|
|
587
|
+
(metric) => !declared.includes(metric)
|
|
588
|
+
);
|
|
589
|
+
if (unknown.length) {
|
|
420
590
|
throw new Error(
|
|
421
|
-
`
|
|
591
|
+
`The tracker's source does not measure ${unknown.join(", ")}`
|
|
422
592
|
);
|
|
423
593
|
}
|
|
424
|
-
return [key2, field.data];
|
|
425
|
-
})
|
|
426
|
-
);
|
|
427
|
-
for (const setting2 of whereSettings(
|
|
428
|
-
definition.trigger.kind === "automatic" ? definition.trigger.tracker?.where : void 0
|
|
429
|
-
)) {
|
|
430
|
-
if (fields[setting2]?.kind !== "integer") {
|
|
431
|
-
throw new Error(
|
|
432
|
-
`The tracker filter compares with setting "${setting2}", which is not an integer setting`
|
|
433
|
-
);
|
|
434
594
|
}
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
const
|
|
439
|
-
|
|
440
|
-
|
|
595
|
+
if (definition.trigger.kind === "manual" && definition.trigger.input !== "none" && !definition.evaluate) {
|
|
596
|
+
throw new Error("Evidence quests require an evaluator");
|
|
597
|
+
}
|
|
598
|
+
const fields = Object.fromEntries(
|
|
599
|
+
Object.entries(definition.settings.shape).map(([key2, schema]) => {
|
|
600
|
+
const field = settingFieldSchema.safeParse(schema.meta());
|
|
601
|
+
if (!field.success) {
|
|
602
|
+
throw new Error(
|
|
603
|
+
`Setting "${key2}" is not a quest setting: build it with a settings builder, such as settings.integer({ label, default, min, max })`
|
|
604
|
+
);
|
|
605
|
+
}
|
|
606
|
+
return [key2, field.data];
|
|
607
|
+
})
|
|
441
608
|
);
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
completion: definition.completion.kind === "streak" ? definition.completion : { kind: definition.completion.kind },
|
|
470
|
-
visibility: definition.visibility ?? "visible",
|
|
471
|
-
// Only when set: a release without the key is hidden and stays readable by older clients.
|
|
472
|
-
...definition.profile ? { profile: definition.profile } : {},
|
|
473
|
-
budgets: definition.budgets ?? [],
|
|
474
|
-
requires: definition.requires ?? []
|
|
475
|
-
});
|
|
476
|
-
}
|
|
477
|
-
return {
|
|
478
|
-
key,
|
|
479
|
-
/** @deprecated Authoring key alias. Use key. */
|
|
480
|
-
id: key,
|
|
481
|
-
describe,
|
|
482
|
-
async evaluate(ctx) {
|
|
483
|
-
const settings2 = definition.settings.parse(ctx.settings);
|
|
484
|
-
const pinned = trackerTrigger ? trackerTriggerContextSchema.parse(ctx.tracker) : null;
|
|
485
|
-
const schema = triggerDataSchemas.get(definition.trigger);
|
|
486
|
-
const dataIssue = pinned && schema ? trackerDataIssue(schema, pinned.record.data) : null;
|
|
487
|
-
if (dataIssue) {
|
|
488
|
-
return decisionSchema.parse({
|
|
489
|
-
kind: "reject",
|
|
490
|
-
reason: `The record's data does not match the data schema this quest was built with: ${dataIssue.path} ${dataIssue.reason}`
|
|
491
|
-
});
|
|
609
|
+
for (const setting2 of whereSettings(
|
|
610
|
+
definition.trigger.kind === "automatic" ? definition.trigger.tracker?.where : void 0
|
|
611
|
+
)) {
|
|
612
|
+
if (fields[setting2]?.kind !== "integer") {
|
|
613
|
+
throw new Error(
|
|
614
|
+
`The tracker filter compares with setting "${setting2}", which is not an integer setting`
|
|
615
|
+
);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
function describe(input) {
|
|
619
|
+
const settings2 = definition.settings.parse(input);
|
|
620
|
+
const values = parseSettings(fields, settings2);
|
|
621
|
+
const rewards = rewardBundleSchema.parse(
|
|
622
|
+
typeof definition.rewards === "function" ? definition.rewards({ settings: settings2 }) : definition.rewards
|
|
623
|
+
);
|
|
624
|
+
const required = [
|
|
625
|
+
...rewards.flatMap(
|
|
626
|
+
(reward) => reward.kind === "integration" ? [reward.provider] : []
|
|
627
|
+
),
|
|
628
|
+
...Object.values(fields).flatMap(
|
|
629
|
+
(field) => field.kind === "resource" && field.source.provider !== "domino" ? [field.source.provider] : []
|
|
630
|
+
)
|
|
631
|
+
];
|
|
632
|
+
for (const provider of required) {
|
|
633
|
+
if (!integrations.includes(provider)) {
|
|
634
|
+
throw new Error(`Declare the ${provider} integration on this quest`);
|
|
635
|
+
}
|
|
492
636
|
}
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
637
|
+
return questDescriptionSchema.parse({
|
|
638
|
+
quest: key,
|
|
639
|
+
evaluatorProtocol,
|
|
640
|
+
title: typeof definition.title === "function" ? definition.title({ settings: settings2 }) : definition.title,
|
|
641
|
+
presentation: definition.presentation?.({ settings: settings2 }) ?? {},
|
|
642
|
+
fields,
|
|
643
|
+
values,
|
|
644
|
+
rewards,
|
|
645
|
+
humanReview: definition.review?.({ settings: settings2 })?.enabled ?? true,
|
|
646
|
+
trigger: definition.trigger,
|
|
647
|
+
...definition.performance ? {
|
|
648
|
+
performance: contentPerformancePolicySchema.parse({
|
|
649
|
+
metrics: definition.performance.metrics,
|
|
650
|
+
maxAgeMs: definition.performance.maxAgeMs
|
|
651
|
+
})
|
|
652
|
+
} : {},
|
|
653
|
+
integrations,
|
|
654
|
+
// A content quest's completion is keyed by its content item, with a key Relay owns.
|
|
655
|
+
completion: !completion ? { kind: "keyed" } : completion.kind === "progress" ? {
|
|
656
|
+
kind: completion.kind,
|
|
657
|
+
goal: completion.goal,
|
|
658
|
+
window: completion.window,
|
|
659
|
+
repeat: completion.repeat
|
|
660
|
+
} : completion.kind === "streak" ? completion : { kind: completion.kind },
|
|
661
|
+
visibility: definition.visibility ?? "visible",
|
|
662
|
+
profile: definition.profile ?? { visible: false },
|
|
663
|
+
budgets: definition.budgets ?? [],
|
|
664
|
+
requires: definition.requires ?? [],
|
|
665
|
+
...definition.campaign ? { campaign: definition.campaign } : {},
|
|
666
|
+
...definition.availability ? { availability: definition.availability } : {}
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
return resourceHandle("quest", {
|
|
670
|
+
protocol: evaluatorProtocol,
|
|
671
|
+
key,
|
|
672
|
+
describe,
|
|
673
|
+
async evaluate(ctx) {
|
|
674
|
+
const settings2 = definition.settings.parse(ctx.settings);
|
|
675
|
+
const pinned = trackerTrigger2 ? trackerTriggerContextSchema.parse(ctx.tracker) : null;
|
|
676
|
+
const schema = triggerDataSchemas.get(definition.trigger);
|
|
677
|
+
const dataIssue = pinned && schema ? trackerDataIssue(schema, pinned.record.data) : null;
|
|
678
|
+
if (dataIssue) {
|
|
679
|
+
return decisionSchema.parse({
|
|
680
|
+
kind: "reject",
|
|
681
|
+
reason: `The record's data does not match the data schema this quest was built with: ${dataIssue.path} ${dataIssue.reason}`
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
const tracker = pinned;
|
|
685
|
+
if (ctx.performance) {
|
|
686
|
+
if (!definition.performance) {
|
|
687
|
+
throw new Error("Quest has no performance evaluator");
|
|
688
|
+
}
|
|
689
|
+
const sample = contentPerformanceSnapshotSchema.parse(ctx.performance);
|
|
690
|
+
const metrics = z3.record(
|
|
691
|
+
z3.enum(definition.performance.metrics),
|
|
692
|
+
z3.number().int().safe().nonnegative()
|
|
693
|
+
).parse(sample.metrics);
|
|
694
|
+
const result2 = await definition.performance.evaluate({
|
|
695
|
+
settings: settings2,
|
|
696
|
+
member: ctx.member,
|
|
697
|
+
tracker,
|
|
698
|
+
metrics,
|
|
699
|
+
observedAt: sample.observedAt
|
|
700
|
+
});
|
|
701
|
+
if (!result2) {
|
|
702
|
+
throw new Error("Performance evaluator returned no decision");
|
|
703
|
+
}
|
|
704
|
+
if (result2.rewards !== void 0) {
|
|
705
|
+
throw new Error(
|
|
706
|
+
"A performance evaluator cannot select rewards. It gates the rewards content evaluation selected: return accept, review or reject with a reason only."
|
|
707
|
+
);
|
|
708
|
+
}
|
|
709
|
+
return decisionSchema.parse(
|
|
710
|
+
result2.kind === "accept" ? { kind: "accept", rewards: sample.rewards } : result2.kind === "review" && ctx.humanReview ? {
|
|
711
|
+
kind: "review",
|
|
712
|
+
reason: result2.reason,
|
|
713
|
+
rewards: sample.rewards
|
|
714
|
+
} : {
|
|
715
|
+
kind: "reject",
|
|
716
|
+
reason: result2.reason,
|
|
717
|
+
...result2.kind === "review" ? { requestedReview: true } : {}
|
|
718
|
+
}
|
|
719
|
+
);
|
|
497
720
|
}
|
|
498
|
-
const
|
|
499
|
-
const metrics = z3.record(
|
|
500
|
-
z3.enum(definition.performance.metrics),
|
|
501
|
-
z3.number().int().safe().nonnegative()
|
|
502
|
-
).parse(sample.metrics);
|
|
503
|
-
const result2 = await definition.performance.evaluate({
|
|
721
|
+
const result = definition.evaluate ? await definition.evaluate({
|
|
504
722
|
settings: settings2,
|
|
505
723
|
member: ctx.member,
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
724
|
+
input: ctx.input,
|
|
725
|
+
tracker,
|
|
726
|
+
eligibleAt: ctx.eligibleAt,
|
|
727
|
+
calendar: ctx.calendar,
|
|
728
|
+
now: ctx.now,
|
|
729
|
+
review: ctx.review,
|
|
730
|
+
trackers: schemaCheckedReader(ctx.trackers),
|
|
731
|
+
wallet: ctx.wallet,
|
|
732
|
+
images: ctx.images,
|
|
733
|
+
// The declared module providers select these keys; unrelated host readers are omitted.
|
|
734
|
+
...Object.fromEntries(
|
|
735
|
+
integrations.map((provider) => [provider, ctx[provider]])
|
|
736
|
+
)
|
|
737
|
+
}) : decision.accept();
|
|
738
|
+
if (!result) {
|
|
739
|
+
throw new Error("Evaluator returned no decision");
|
|
512
740
|
}
|
|
513
|
-
if (
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
741
|
+
if (result.kind === "review" && !ctx.humanReview) {
|
|
742
|
+
return decisionSchema.parse({
|
|
743
|
+
kind: "reject",
|
|
744
|
+
reason: result.reason,
|
|
745
|
+
requestedReview: true
|
|
746
|
+
});
|
|
517
747
|
}
|
|
518
748
|
return decisionSchema.parse(
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
rewards:
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
rewards: sample.rewards
|
|
527
|
-
} : {
|
|
528
|
-
kind: "reject",
|
|
529
|
-
reason: result2.reason,
|
|
530
|
-
...result2.kind === "review" ? { requestedReview: true } : {}
|
|
531
|
-
}
|
|
749
|
+
result.kind === "accept" || result.kind === "review" ? {
|
|
750
|
+
...result,
|
|
751
|
+
rewards: result.rewards ?? ctx.rewards,
|
|
752
|
+
...completion?.kind === "keyed" || completion?.kind === "progress" ? {
|
|
753
|
+
completionKey: completion.kind === "progress" ? completion.distinct({ ...ctx, tracker: pinned }) : result.completionKey ?? completion.key({ ...ctx, tracker: pinned })
|
|
754
|
+
} : {}
|
|
755
|
+
} : result
|
|
532
756
|
);
|
|
533
757
|
}
|
|
534
|
-
|
|
535
|
-
settings: settings2,
|
|
536
|
-
member: ctx.member,
|
|
537
|
-
input: ctx.input,
|
|
538
|
-
content: contentTrigger ? admittedContentSchema.parse(ctx.content) : null,
|
|
539
|
-
observation: ctx.observation ?? null,
|
|
540
|
-
tracker,
|
|
541
|
-
eligibleAt: ctx.eligibleAt,
|
|
542
|
-
now: ctx.now,
|
|
543
|
-
review: ctx.review,
|
|
544
|
-
trackers: schemaCheckedReader(ctx.trackers),
|
|
545
|
-
wallet: ctx.wallet,
|
|
546
|
-
x: ctx.x,
|
|
547
|
-
images: ctx.images,
|
|
548
|
-
discord: ctx.discord
|
|
549
|
-
}) : decision.accept();
|
|
550
|
-
if (!result) {
|
|
551
|
-
throw new Error("Evaluator returned no decision");
|
|
552
|
-
}
|
|
553
|
-
if (result.kind === "review" && !ctx.humanReview) {
|
|
554
|
-
return decisionSchema.parse({
|
|
555
|
-
kind: "reject",
|
|
556
|
-
reason: result.reason,
|
|
557
|
-
requestedReview: true
|
|
558
|
-
});
|
|
559
|
-
}
|
|
560
|
-
return decisionSchema.parse(
|
|
561
|
-
result.kind === "accept" || result.kind === "review" ? {
|
|
562
|
-
...result,
|
|
563
|
-
rewards: result.rewards ?? ctx.rewards,
|
|
564
|
-
...definition.completion.kind === "keyed" ? {
|
|
565
|
-
completionKey: definition.completion.key({
|
|
566
|
-
...ctx,
|
|
567
|
-
observation: ctx.observation ?? null,
|
|
568
|
-
tracker: pinned
|
|
569
|
-
})
|
|
570
|
-
} : {}
|
|
571
|
-
} : result
|
|
572
|
-
);
|
|
573
|
-
}
|
|
758
|
+
});
|
|
574
759
|
};
|
|
575
760
|
}
|
|
576
|
-
var
|
|
761
|
+
var defineQuest = questBuilder(false);
|
|
762
|
+
var defineQuestType = questBuilder(true);
|
|
577
763
|
export {
|
|
764
|
+
CapabilityError,
|
|
578
765
|
automatic,
|
|
766
|
+
automaticFulfillment,
|
|
767
|
+
balanceAtLeast,
|
|
579
768
|
budget,
|
|
769
|
+
calendar,
|
|
770
|
+
capabilityErrorCodes,
|
|
580
771
|
completed,
|
|
581
772
|
content,
|
|
773
|
+
cosmosDenomSchema,
|
|
774
|
+
cosmosNetworkSchema,
|
|
775
|
+
count,
|
|
582
776
|
customSource,
|
|
583
777
|
decision,
|
|
778
|
+
defineCampaign,
|
|
584
779
|
defineEngagementReward,
|
|
780
|
+
defineGroup,
|
|
585
781
|
defineLeaderboard,
|
|
782
|
+
defineLedger,
|
|
783
|
+
defineOffer,
|
|
586
784
|
defineQuest,
|
|
587
785
|
defineQuestType,
|
|
588
786
|
defineReferral,
|
|
589
787
|
defineTieredReward,
|
|
590
788
|
defineTracker,
|
|
591
789
|
discord,
|
|
592
|
-
|
|
790
|
+
earned,
|
|
593
791
|
evaluators,
|
|
594
792
|
evidence,
|
|
595
793
|
formatUnits,
|
|
794
|
+
inGroup,
|
|
596
795
|
isEvmChainId,
|
|
597
796
|
keyed,
|
|
598
797
|
manual,
|
|
599
798
|
once,
|
|
600
799
|
parseUnits,
|
|
601
|
-
perContent,
|
|
602
800
|
pointLedgers,
|
|
603
801
|
points,
|
|
802
|
+
progress,
|
|
803
|
+
questCompleted,
|
|
804
|
+
rolling,
|
|
604
805
|
settings,
|
|
605
806
|
staffHandover,
|
|
606
807
|
streak,
|