@domino-sdk/relay 1.56.0 → 1.60.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 (65) hide show
  1. package/CHANGELOG.md +100 -0
  2. package/dist/{accounts-DRPENuZe.d.ts → accounts-DoabriBX.d.ts} +21 -7
  3. package/dist/{attempt-captures-CxxO7DeD.d.ts → attempt-captures-W2dgzGqE.d.ts} +1 -1
  4. package/dist/authoring.d.ts +323 -39
  5. package/dist/authoring.js +312 -18
  6. package/dist/{automatic-outcomes-DxW_v5Wc.d.ts → automatic-outcomes-Cmou89IS.d.ts} +1 -1
  7. package/dist/avatar.d.ts +1 -2
  8. package/dist/browser.d.ts +19 -11
  9. package/dist/browser.js +12 -10
  10. package/dist/{capability-error-DSd8EMQC.d.ts → capability-error-DufwG3G0.d.ts} +21 -7
  11. package/dist/{chunk-OTITLABX.js → chunk-2FHNY52R.js} +8 -2
  12. package/dist/{chunk-QNQNKIAA.js → chunk-422J3QRW.js} +12 -2
  13. package/dist/{chunk-INSWI2VZ.js → chunk-4OFH4BNX.js} +1 -1
  14. package/dist/{chunk-KBVH4XZC.js → chunk-6ZG7WNYX.js} +1 -1
  15. package/dist/{chunk-BHHUSBSD.js → chunk-GBSDAD3N.js} +1627 -887
  16. package/dist/{chunk-W5U2WXG3.js → chunk-KUPVQXUJ.js} +2 -2
  17. package/dist/{chunk-G6XVBYH7.js → chunk-KWFY7L7X.js} +4 -4
  18. package/dist/{chunk-BJYMTCWG.js → chunk-MJEJQH5A.js} +18 -6
  19. package/dist/{chunk-ULQU7KC4.js → chunk-N3LJ6GFK.js} +1 -5
  20. package/dist/{chunk-ABJ4G47X.js → chunk-N7YOS4ZU.js} +1 -1
  21. package/dist/{chunk-MNU6UPXY.js → chunk-OTEUP2SG.js} +1 -1
  22. package/dist/{chunk-NK6EER33.js → chunk-VVRQQRMQ.js} +12 -12
  23. package/dist/{chunk-H2MD6E7Z.js → chunk-VWMIA2TT.js} +8 -2
  24. package/dist/{chunk-RBPMT53S.js → chunk-XQKUJL7H.js} +25 -5
  25. package/dist/{chunk-CXKXPB7K.js → chunk-Y2IGFLD2.js} +36 -11
  26. package/dist/{chunk-VSHV7FEA.js → chunk-YNW2ZUUP.js} +56 -153
  27. package/dist/{chunk-CK7HO32Z.js → chunk-YOAPPIWN.js} +2 -2
  28. package/dist/{client-bX3oTpRu.d.ts → client-Cw1pB5sv.d.ts} +121 -117
  29. package/dist/{deployments-D3lxfQMB.d.ts → deployments-DI-W7fBq.d.ts} +1105 -182
  30. package/dist/{groups-DPE004_V.d.ts → groups-9Jm3peq3.d.ts} +14 -7
  31. package/dist/index.d.ts +10 -11
  32. package/dist/index.js +9 -9
  33. package/dist/{integrations-CcD5NPEA.d.ts → integrations-CmIkP1Gi.d.ts} +48 -32
  34. package/dist/internal.d.ts +10 -10
  35. package/dist/internal.js +8 -8
  36. package/dist/{offers-CtzMeB7O.d.ts → offers-CqXfMIxq.d.ts} +7 -2
  37. package/dist/{pages-BlLqB8ZQ.d.ts → pages-Bti7g5mX.d.ts} +184 -10
  38. package/dist/{participant-activity-iciCEs_8.d.ts → participant-activity-DHL8QYks.d.ts} +4 -0
  39. package/dist/portal-proxy.js +3 -3
  40. package/dist/react/index.d.ts +74 -74
  41. package/dist/react/index.js +10 -10
  42. package/dist/runtime/authoring.js +1 -1
  43. package/dist/runtime/chunks/ADUMK6CR.js +1 -0
  44. package/dist/runtime/chunks/EWU4OKSY.js +62 -0
  45. package/dist/runtime/manifest.json +5 -5
  46. package/dist/runtime/schema.js +1 -1
  47. package/dist/runtime/zod.js +1 -1
  48. package/dist/{schema-C4m9RhCR.d.ts → schema-CwbRkmlr.d.ts} +324 -35
  49. package/dist/schema.d.ts +854 -437
  50. package/dist/schema.js +103 -25
  51. package/dist/server/index.d.ts +10 -10
  52. package/dist/server/index.js +711 -81
  53. package/dist/{submission-input-wTiYGdgA.d.ts → submission-input-D9EGH_yb.d.ts} +2 -2
  54. package/dist/{telegram-browser-Bh3i0HiH.d.ts → telegram-browser-CTJh4Ro_.d.ts} +4 -4
  55. package/dist/testing.d.ts +89 -9
  56. package/dist/testing.js +218 -13
  57. package/dist/{transport-CnKA-_RL.d.ts → transport-B8Ss5lcz.d.ts} +9189 -2009
  58. package/dist/wallet-DZWL7lJH.d.ts +972 -0
  59. package/dist/{x-1czZFVUW.d.ts → x-KFJD2x8y.d.ts} +3 -3
  60. package/package.json +2 -2
  61. package/dist/profiles-BoOK03cR.d.ts +0 -299
  62. package/dist/runtime/chunks/IDOMZWRY.js +0 -40
  63. package/dist/runtime/chunks/NDB42VFF.js +0 -1
  64. package/dist/util.d-w9f9t3ua.d.ts +0 -5
  65. package/dist/wallet-Ac7OFpOr.d.ts +0 -228
package/dist/authoring.js CHANGED
@@ -6,11 +6,9 @@ import {
6
6
  defineDashboard,
7
7
  tiktokVideoBodySchema,
8
8
  tiktokVideoMetrics,
9
- tiktokVideosNamespace,
10
9
  youtubeShortBodySchema,
11
- youtubeShortMetrics,
12
- youtubeShortsNamespace
13
- } from "./chunk-ULQU7KC4.js";
10
+ youtubeShortMetrics
11
+ } from "./chunk-N3LJ6GFK.js";
14
12
  import {
15
13
  CapabilityError,
16
14
  capabilityErrorCodes
@@ -19,7 +17,7 @@ import {
19
17
  sourceDataSchema,
20
18
  sourceRoles,
21
19
  validateQuestShape
22
- } from "./chunk-H2MD6E7Z.js";
20
+ } from "./chunk-VWMIA2TT.js";
23
21
  import {
24
22
  badgeDeclarationSchema,
25
23
  defineOffer,
@@ -28,13 +26,13 @@ import {
28
26
  engagementScoreSchema,
29
27
  leaderboardAuthoringSchema,
30
28
  referralAuthoringSchema
31
- } from "./chunk-BJYMTCWG.js";
29
+ } from "./chunk-MJEJQH5A.js";
32
30
  import {
33
- pointLedgerDeclarationSchema,
34
- telegramReactionDataSchema,
35
- telegramReactionsNamespace
36
- } from "./chunk-VSHV7FEA.js";
31
+ pointLedgerDeclarationSchema
32
+ } from "./chunk-YNW2ZUUP.js";
37
33
  import {
34
+ announcementSchema,
35
+ authorBudgetSchema,
38
36
  authoringKey,
39
37
  badgeReward,
40
38
  balanceAtLeast,
@@ -53,6 +51,7 @@ import {
53
51
  defaultTriggerMode,
54
52
  defineCampaign,
55
53
  defineGroup,
54
+ discordAnnouncementSchema,
56
55
  discordMessagesSourceSchema,
57
56
  discordReactionsSourceSchema,
58
57
  discordRewardSchema,
@@ -64,9 +63,22 @@ import {
64
63
  isAmount,
65
64
  isBalanceChain,
66
65
  isBoundSetting,
66
+ isContractCall,
67
+ isContractEvent,
67
68
  isEvmChainId,
69
+ isNftCollection,
70
+ isSolanaProgram,
68
71
  ledgerKey,
69
72
  ledgerSettingSchema,
73
+ maxWalletEventLogs,
74
+ maxWalletEventLookback,
75
+ maxWalletTransactionLookback,
76
+ maxWalletTransactions,
77
+ parseAnnouncementTemplate,
78
+ parseContractCall,
79
+ parseContractEvent,
80
+ parseContractFunction,
81
+ parseNftCollection,
70
82
  parseSettings,
71
83
  pointsRewardSchema,
72
84
  questDescriptionSchema,
@@ -81,23 +93,34 @@ import {
81
93
  settingFieldSchema,
82
94
  settingInstant,
83
95
  settingResourceId,
96
+ solanaAddressSchema,
97
+ solanaMainnet,
84
98
  sourceContent,
85
99
  sourceIdentities,
86
100
  streakPolicySchema,
101
+ telegramAnnouncementSchema,
102
+ telegramMessageDataSchema,
103
+ telegramMessagesNamespace,
104
+ telegramReactionDataSchema,
105
+ telegramReactionsNamespace,
87
106
  textOptionsSchema,
88
107
  textSettingSchema,
89
108
  tierRewardSchema,
90
109
  tieredRewardDefinitionSchema,
110
+ tiktokVideosNamespace,
91
111
  trackerDataIssue,
92
112
  trackerDataSchema,
93
113
  trackerDefinitionSchema,
94
114
  trackerTriggerContextSchema,
95
115
  trackerTriggerPolicySchema,
96
116
  urlOptionsSchema,
117
+ walletBalanceSampleSchema,
118
+ walletBalancesNamespace,
97
119
  whereSchemaIssue,
98
120
  whereSettings,
99
- xSearchSourceSchema
100
- } from "./chunk-BHHUSBSD.js";
121
+ xSearchSourceSchema,
122
+ youtubeShortsNamespace
123
+ } from "./chunk-GBSDAD3N.js";
101
124
 
102
125
  // src/builders.ts
103
126
  import * as z from "zod";
@@ -274,6 +297,19 @@ var discord = {
274
297
  action: "grant-role",
275
298
  roleId
276
299
  }),
300
+ /**
301
+ * An announcement Domino's bot posts in a channel of the project's Discord server when a
302
+ * completion pays, such as `"{beneficiary} got +{points} XP from {author}"`. Placeholders are
303
+ * `announcementPlaceholders`; `{beneficiary}` and `{author}` mention linked Discord accounts.
304
+ * Pass it in the quest's `announcements`, and declare the `discord` integration.
305
+ */
306
+ postMessage(options) {
307
+ return discordAnnouncementSchema.parse({
308
+ provider: "discord",
309
+ action: "post-message",
310
+ ...options
311
+ });
312
+ },
277
313
  messages,
278
314
  reactions,
279
315
  roles(options = {}) {
@@ -283,15 +319,40 @@ var discord = {
283
319
  assignable: options.assignable ?? false
284
320
  });
285
321
  },
322
+ /**
323
+ * A channel of the project's Discord server, for a resource setting. With `postable: true`,
324
+ * Console lists channels Domino's bot cannot post in as unavailable, as an announcement's
325
+ * channel needs.
326
+ */
286
327
  channels(options = {}) {
287
328
  return resourceSourceSchema.parse({
288
329
  provider: "discord",
289
330
  resource: "channel",
290
- types: options.types ?? ["text", "announcement"]
331
+ types: options.types ?? ["text", "announcement"],
332
+ ...options.postable ? { postable: true } : {}
291
333
  });
292
334
  }
293
335
  };
294
336
  var telegram = {
337
+ /**
338
+ * An announcement Domino's bot posts in a connected chat when a completion pays, such as
339
+ * `"{beneficiary} got +{points} XP from {author}"`. Name the chat with `settings.telegramChat()`.
340
+ * Placeholders are `announcementPlaceholders`; `{beneficiary}` and `{author}` mention Telegram
341
+ * accounts. Pass it in the quest's `announcements`.
342
+ */
343
+ postMessage(options) {
344
+ return telegramAnnouncementSchema.parse({
345
+ provider: "telegram",
346
+ action: "post-message",
347
+ ...options
348
+ });
349
+ },
350
+ messages() {
351
+ return customSource(telegramMessagesNamespace, {
352
+ identities: ["member"],
353
+ data: telegramMessageDataSchema
354
+ });
355
+ },
295
356
  reactions() {
296
357
  return customSource(telegramReactionsNamespace, {
297
358
  identities: ["member"],
@@ -322,6 +383,50 @@ var tiktok = {
322
383
  });
323
384
  }
324
385
  };
386
+ function walletBalanceSource(query) {
387
+ const { chain, token } = query;
388
+ const given = token === void 0 ? null : token;
389
+ if (given !== null && typeof given !== "string") {
390
+ throw new Error("wallet.balances() takes the token as a string");
391
+ }
392
+ if (chain === "solana" || chain === solanaMainnet) {
393
+ if (given !== null && !solanaAddressSchema.safeParse(given).success) {
394
+ throw new Error(
395
+ "wallet.balances() on Solana takes an SPL or Token-2022 mint address (base58)"
396
+ );
397
+ }
398
+ return { chain: solanaMainnet, token: given };
399
+ }
400
+ if (typeof chain === "string" && isEvmChainId(chain)) {
401
+ if (given !== null && !/^0x[0-9a-fA-F]{40}$/.test(given)) {
402
+ throw new Error(
403
+ "wallet.balances() on an EVM chain takes an ERC-20 contract address: 0x and 40 hex digits"
404
+ );
405
+ }
406
+ return { chain, token: given };
407
+ }
408
+ if (typeof chain === "string" && /^cosmos:[-_a-zA-Z0-9]{1,32}$/.test(chain)) {
409
+ if (given === null || !cosmosDenomSchema.safeParse(given).success) {
410
+ throw new Error(
411
+ "wallet.balances() on a Cosmos chain takes a bank denomination such as uatom"
412
+ );
413
+ }
414
+ return { chain, token: given };
415
+ }
416
+ throw new Error(
417
+ 'wallet.balances() reads "solana", an EVM chain such as "eip155:8453" or a Cosmos network such as "cosmos:cosmoshub-4"'
418
+ );
419
+ }
420
+ var wallet = {
421
+ balances(query) {
422
+ const balance = walletBalanceSource(query);
423
+ const source = customSource(walletBalancesNamespace, {
424
+ identities: ["wallet"],
425
+ data: walletBalanceSampleSchema
426
+ });
427
+ return customSourceSchema.parse({ ...source, balance });
428
+ }
429
+ };
325
430
  var pointLedgers = () => ({
326
431
  provider: "domino",
327
432
  resource: "point-ledger"
@@ -451,6 +556,114 @@ var settings = {
451
556
  textSettingSchema(field).transform((value) => value).default(field.default).meta(field)
452
557
  );
453
558
  },
559
+ /**
560
+ * An NFT collection `ctx.wallet.nfts()` reads, as a CAIP-19 asset type: an EVM chain, the
561
+ * standard and the contract, such as `"eip155:1/erc721:0x…"`, or `"eip155:8453/erc1155:0x…/1"` for
562
+ * one ERC-1155 token ID; or a Metaplex collection NFT's mint on Solana mainnet,
563
+ * `"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/nft:<mint>"`. Relay checks it when the collection is
564
+ * published or edited: an EVM chain must be one `ctx.wallet.balance()` reads and the contract
565
+ * must report the standard through ERC-165 `supportsInterface`; a Solana mint must be a Metaplex
566
+ * collection NFT. Typed as the query's collection, so it passes to
567
+ * `ctx.wallet.nfts({ collection })` as it is.
568
+ */
569
+ nft(options) {
570
+ if (!isNftCollection(options.default)) {
571
+ throw new Error(
572
+ `settings.nft() takes an NFT collection such as "eip155:1/erc721:0x\u2026" as its default, not "${options.default}"`
573
+ );
574
+ }
575
+ const field = {
576
+ ...options,
577
+ kind: "text",
578
+ minLength: 1,
579
+ maxLength: 200,
580
+ multiline: false,
581
+ picker: "nft"
582
+ };
583
+ return setting(
584
+ "text",
585
+ textSettingSchema(field).transform((value) => value).default(field.default).meta(field)
586
+ );
587
+ },
588
+ /**
589
+ * A contract function `ctx.wallet.call()` reads: the contract's CAIP-10 account ID on an EVM
590
+ * chain, a space, and the function's human-readable signature, such as
591
+ * `"eip155:8453:0x… function stakedOf(address) view returns (uint256)"`. Only `view` and `pure`
592
+ * functions with elementary parameters that return one `uint`, `int`, `bool` or `address` are
593
+ * accepted; publication and Console edits also check that Relay reads the chain. Typed as the
594
+ * query's call, so it passes to `ctx.wallet.call({ call })` as it is.
595
+ */
596
+ contractCall(options) {
597
+ if (!isContractCall(options.default)) {
598
+ throw new Error(
599
+ `settings.contractCall() takes a contract call such as "eip155:8453:0x\u2026 function stakedOf(address) view returns (uint256)" as its default, not "${options.default}"`
600
+ );
601
+ }
602
+ const field = {
603
+ ...options,
604
+ kind: "text",
605
+ minLength: 1,
606
+ maxLength: 400,
607
+ multiline: false,
608
+ picker: "contract-call"
609
+ };
610
+ return setting(
611
+ "text",
612
+ textSettingSchema(field).transform((value) => value).default(field.default).meta(field)
613
+ );
614
+ },
615
+ /**
616
+ * An EVM contract event `ctx.wallet.events()` reads: the contract as a CAIP-10 account ID and
617
+ * the event's Solidity signature, with argument names and `indexed` markers, such as
618
+ * `"eip155:8453:0x… Transfer(address indexed from, address indexed to, uint256 value)"`. The event
619
+ * needs an indexed `address` argument, the one matched against the member's wallets. Relay checks
620
+ * it when the event is published or edited: the chain must be one `ctx.wallet.balance()` reads
621
+ * and report a finalized or safe block, and the address must hold a contract. Typed as the query's
622
+ * event, so it passes to `ctx.wallet.events({ event })` as it is.
623
+ */
624
+ contractEvent(options) {
625
+ if (!isContractEvent(options.default)) {
626
+ throw new Error(
627
+ `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 "${options.default}"`
628
+ );
629
+ }
630
+ const field = {
631
+ ...options,
632
+ kind: "text",
633
+ minLength: 1,
634
+ maxLength: 1e3,
635
+ multiline: false,
636
+ picker: "contract-event"
637
+ };
638
+ return setting(
639
+ "text",
640
+ textSettingSchema(field).transform((value) => value).default(field.default).meta(field)
641
+ );
642
+ },
643
+ /**
644
+ * A Solana mainnet program `ctx.wallet.transactions()` reads: its base58 address, such as
645
+ * Jupiter's `"JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"`. Relay checks it when it is published
646
+ * or edited: the account must exist and be an executable program.
647
+ */
648
+ solanaProgram(options) {
649
+ if (!isSolanaProgram(options.default)) {
650
+ throw new Error(
651
+ `settings.solanaProgram() takes a Solana program address such as "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4" as its default, not "${options.default}"`
652
+ );
653
+ }
654
+ const field = {
655
+ ...options,
656
+ kind: "text",
657
+ minLength: 32,
658
+ maxLength: 44,
659
+ multiline: false,
660
+ picker: "solana-program"
661
+ };
662
+ return setting(
663
+ "text",
664
+ textSettingSchema(field).transform((value) => value).default(field.default).meta(field)
665
+ );
666
+ },
454
667
  integer(options) {
455
668
  return setting(
456
669
  "integer",
@@ -478,6 +691,37 @@ var settings = {
478
691
  // src/authoring.ts
479
692
  import { z as z2 } from "zod";
480
693
  import * as z3 from "zod";
694
+
695
+ // src/solana-transactions.ts
696
+ function delta(tx, mint) {
697
+ const change = tx.balanceChanges.find((entry) => entry.mint === mint);
698
+ return change ? BigInt(change.delta) : 0n;
699
+ }
700
+ function received(tx, mint) {
701
+ const change = delta(tx, mint);
702
+ return change > 0n ? change.toString() : "0";
703
+ }
704
+ function spent(tx, mint) {
705
+ const change = delta(tx, mint);
706
+ return change < 0n ? (-change).toString() : "0";
707
+ }
708
+ function swapped(tx, options = {}) {
709
+ const up = tx.balanceChanges.filter((change) => BigInt(change.delta) > 0n);
710
+ const down = tx.balanceChanges.filter((change) => BigInt(change.delta) < 0n);
711
+ return up.some(
712
+ (gained) => (options.into === void 0 || gained.mint === options.into) && down.some(
713
+ (gave) => gave.mint !== gained.mint && (options.from === void 0 || gave.mint === options.from)
714
+ )
715
+ );
716
+ }
717
+ function invoked(tx, program) {
718
+ return tx.programs.includes(program);
719
+ }
720
+ function instruction(tx, name) {
721
+ return tx.instructions?.find((entry) => entry.name === name)?.args ?? null;
722
+ }
723
+
724
+ // src/authoring.ts
481
725
  var badge = (definition) => badgeReward(definition.key, definition.name);
482
726
  var groupMembership = (group) => groupReward(group.key, group.title);
483
727
  var points = (ledger, amount) => pointsRewardSchema.parse({
@@ -594,14 +838,17 @@ function content(input) {
594
838
  }
595
839
  return trackerTrigger({ ...input, content: true }, "content");
596
840
  }
597
- var budget = (definition) => {
841
+ function defineBudget(definition) {
598
842
  const { key: _, cost, ...properties } = definition;
599
- return budgetSchema.parse({
843
+ const parsed = {
600
844
  ...properties,
601
845
  id: authoringKey(definition),
602
846
  cost: typeof cost === "number" ? cost : { balance: ledgerKey(cost.ledger) }
603
- });
604
- };
847
+ };
848
+ return properties.scope === "author" ? authorBudgetSchema.parse(parsed) : budgetSchema.parse(parsed);
849
+ }
850
+ var budget = defineBudget;
851
+ var authorBudgets = (budgets = []) => budgets.filter((value) => value.scope === "author");
605
852
  var keyed = (key) => ({
606
853
  kind: "keyed",
607
854
  key
@@ -721,11 +968,13 @@ function questBuilder(template) {
721
968
  "A quest needs a completion, such as once(), keyed(...), streak(...) or progress(...)"
722
969
  );
723
970
  }
971
+ const author = authorBudgets(definition.budgets);
724
972
  validateQuestShape(
725
973
  {
726
974
  trigger: definition.trigger,
727
975
  completion: completion ?? { kind: "keyed" },
728
976
  requires: definition.requires ?? [],
977
+ authorBudgets: author,
729
978
  performance: definition.performance ? contentPerformancePolicySchema.parse({
730
979
  metrics: definition.performance.metrics,
731
980
  maxAgeMs: definition.performance.maxAgeMs
@@ -785,10 +1034,33 @@ function questBuilder(template) {
785
1034
  const rewards = rewardBundleSchema.parse(
786
1035
  typeof definition.rewards === "function" ? definition.rewards({ settings: settings2 }) : definition.rewards
787
1036
  );
1037
+ const announcements = z3.array(announcementSchema).max(3, "A quest posts at most three announcements").parse(
1038
+ (typeof definition.announcements === "function" ? definition.announcements({ settings: settings2 }) : definition.announcements) ?? []
1039
+ );
1040
+ const trackerTrigger3 = definition.trigger.kind === "automatic" && definition.trigger.tracker !== void 0;
1041
+ for (const announcement of announcements) {
1042
+ const parsed = parseAnnouncementTemplate(announcement.text);
1043
+ const usesAuthor = "segments" in parsed && parsed.segments.some(
1044
+ (segment) => segment.kind === "placeholder" && segment.name === "author"
1045
+ );
1046
+ if (!trackerTrigger3 && usesAuthor) {
1047
+ throw new Error(
1048
+ "An announcement names {author} only on a quest with an automatic tracker trigger"
1049
+ );
1050
+ }
1051
+ if (!trackerTrigger3 && announcement.replyToTriggeringMessage) {
1052
+ throw new Error(
1053
+ "An announcement replies to the triggering message only on a quest with an automatic tracker trigger"
1054
+ );
1055
+ }
1056
+ }
788
1057
  const required = [
789
1058
  ...rewards.flatMap(
790
1059
  (reward) => reward.kind === "integration" ? [reward.provider] : []
791
1060
  ),
1061
+ ...announcements.flatMap(
1062
+ (announcement) => announcement.provider === "discord" ? ["discord"] : []
1063
+ ),
792
1064
  ...Object.values(fields).flatMap(
793
1065
  (field) => field.kind === "resource" && field.source.provider !== "domino" ? [field.source.provider] : []
794
1066
  )
@@ -806,6 +1078,7 @@ function questBuilder(template) {
806
1078
  fields,
807
1079
  values,
808
1080
  rewards,
1081
+ ...announcements.length ? { announcements } : {},
809
1082
  humanReview: definition.review?.({ settings: settings2 })?.enabled ?? true,
810
1083
  trigger: definition.trigger,
811
1084
  ...definition.performance ? {
@@ -824,7 +1097,10 @@ function questBuilder(template) {
824
1097
  } : completion.kind === "streak" ? completion : { kind: completion.kind },
825
1098
  visibility: definition.visibility ?? "visible",
826
1099
  profile: definition.profile ?? { visible: false },
827
- budgets: definition.budgets ?? [],
1100
+ budgets: (definition.budgets ?? []).filter(
1101
+ (value) => value.scope !== "author"
1102
+ ),
1103
+ ...author.length ? { authorBudgets: author } : {},
828
1104
  requires: definition.requires ?? [],
829
1105
  ...definition.campaign ? { campaign: definition.campaign } : {},
830
1106
  ...definition.availability ? { availability: definition.availability } : {},
@@ -985,24 +1261,42 @@ export {
985
1261
  formatUnits,
986
1262
  groupMembership,
987
1263
  inGroup,
1264
+ instruction,
1265
+ invoked,
1266
+ isContractCall,
1267
+ isContractEvent,
988
1268
  isEvmChainId,
1269
+ isNftCollection,
1270
+ isSolanaProgram,
989
1271
  keyed,
990
1272
  manual,
1273
+ maxWalletEventLogs,
1274
+ maxWalletEventLookback,
1275
+ maxWalletTransactionLookback,
1276
+ maxWalletTransactions,
991
1277
  once,
1278
+ parseContractCall,
1279
+ parseContractEvent,
1280
+ parseContractFunction,
1281
+ parseNftCollection,
992
1282
  parseUnits,
993
1283
  pointLedgers,
994
1284
  points,
995
1285
  progress,
996
1286
  questCompleted,
1287
+ received,
997
1288
  rolling,
998
1289
  settings,
1290
+ spent,
999
1291
  staffHandover,
1000
1292
  streak,
1293
+ swapped,
1001
1294
  telegram,
1002
1295
  tiktok,
1003
1296
  trackerDataSchema,
1004
1297
  trackerTriggerContextSchema,
1005
1298
  untracked,
1299
+ wallet,
1006
1300
  x,
1007
1301
  youtube,
1008
1302
  z2 as z
@@ -1,5 +1,5 @@
1
1
  import * as z from 'zod';
2
- import { a as AttemptStatus } from './schema-C4m9RhCR.js';
2
+ import { a as AttemptStatus } from './schema-CwbRkmlr.js';
3
3
 
4
4
  declare const collectionCodeSchema: z.ZodString;
5
5
  declare const collectionPassSchema: z.ZodObject<{
package/dist/avatar.d.ts CHANGED
@@ -1,5 +1,4 @@
1
- import { L as LinkedWallet } from './wallet-Ac7OFpOr.js';
2
- import { P as ProfileAvatar } from './profiles-BoOK03cR.js';
1
+ import { P as ProfileAvatar, L as LinkedWallet } from './wallet-DZWL7lJH.js';
3
2
  import 'zod';
4
3
 
5
4
  /**
package/dist/browser.d.ts CHANGED
@@ -1,16 +1,24 @@
1
- import { o as SubmissionStore, f as RelayClientOptions, R as RelayClient } from './client-bX3oTpRu.js';
2
- export { C as CosmosChains, D as DiscoveredWallet, E as Eip1193Provider, a as EmailSignInOption, K as KeplrLike, O as OAuthSignInOption, S as SignInClient, b as SignInIcon, c as SignInMethods, d as SignInOption, e as SignInOptions, f as SignInUnavailable, g as SignInWallet, h as SolanaInjectedProvider, i as StandardWallet, j as StandardWalletAccount, T as TelegramSignInOption, W as WalletSignInOption, k as cosmosChainList, l as cosmosSigner, m as discoverCosmosWallets, n as discoverEvmWallets, o as discoverSignInWallets, p as discoverSolanaWallets, q as evmSigner, s as signInOptions, r as solanaSigner, t as telegramMiniAppInitData, w as walletStandardSolanaSigner } from './telegram-browser-Bh3i0HiH.js';
1
+ import { o as SubmissionStore, f as RelayClientOptions, R as RelayClient } from './client-Cw1pB5sv.js';
2
+ export { C as CosmosChains, D as DiscoveredWallet, E as Eip1193Provider, a as EmailSignInOption, K as KeplrLike, O as OAuthSignInOption, S as SignInClient, b as SignInIcon, c as SignInMethods, d as SignInOption, e as SignInOptions, f as SignInUnavailable, g as SignInWallet, h as SolanaInjectedProvider, i as StandardWallet, j as StandardWalletAccount, T as TelegramSignInOption, W as WalletSignInOption, k as cosmosChainList, l as cosmosSigner, m as discoverCosmosWallets, n as discoverEvmWallets, o as discoverSignInWallets, p as discoverSolanaWallets, q as evmSigner, s as signInOptions, r as solanaSigner, t as telegramMiniAppInitData, w as walletStandardSolanaSigner } from './telegram-browser-CTJh4Ro_.js';
3
3
  export { H as HostEnvironment, g as getHostEnvironment } from './host-environment-FN4zg3hw.js';
4
- import './schema-C4m9RhCR.js';
4
+ import { M as MemberSummary } from './participant-activity-DHL8QYks.js';
5
+ import './schema-CwbRkmlr.js';
5
6
  import 'zod';
6
- import './pages-BlLqB8ZQ.js';
7
- import './submission-input-wTiYGdgA.js';
8
- import './groups-DPE004_V.js';
7
+ import './wallet-DZWL7lJH.js';
8
+ import './pages-Bti7g5mX.js';
9
+ import './submission-input-D9EGH_yb.js';
10
+ import './groups-9Jm3peq3.js';
9
11
  import './action-DBzILFx9.js';
10
- import './participant-activity-iciCEs_8.js';
11
- import './accounts-DRPENuZe.js';
12
- import './profiles-BoOK03cR.js';
13
- import './wallet-Ac7OFpOr.js';
12
+ import './accounts-DoabriBX.js';
13
+
14
+ /**
15
+ * The member's time at the real instant `at` (default now), in epoch milliseconds: what an app
16
+ * compares campaign phases and quest dates against, so it shows what Relay judges on. Applies
17
+ * `me.clock.offsetMs` from `GET /v1/me`, which moves when the staging toolbar moves a test member's
18
+ * clock; read `/v1/me` again on `domino:test-state-changed`. Without `clock` (a Relay older than
19
+ * it) the member's time is real time.
20
+ */
21
+ declare function memberTime(me: Pick<MemberSummary, "clock">, at?: number): number;
14
22
 
15
23
  /** Browser client with durable submission recovery; safe to construct during SSR. */
16
24
  declare function createBrowserRelayClient(options: RelayClientOptions): RelayClient;
@@ -22,4 +30,4 @@ declare function createBrowserRelayClient(options: RelayClientOptions): RelayCli
22
30
  */
23
31
  declare function browserSubmissionStore(): SubmissionStore;
24
32
 
25
- export { browserSubmissionStore, createBrowserRelayClient };
33
+ export { browserSubmissionStore, createBrowserRelayClient, memberTime };
package/dist/browser.js CHANGED
@@ -8,23 +8,24 @@ import {
8
8
  discoverSignInWallets,
9
9
  discoverSolanaWallets,
10
10
  evmSigner,
11
+ memberTime,
11
12
  signInOptions,
12
13
  solanaSigner,
13
14
  telegramMiniAppInitData,
14
15
  walletStandardSolanaSigner
15
- } from "./chunk-OTITLABX.js";
16
- import "./chunk-NK6EER33.js";
17
- import "./chunk-INSWI2VZ.js";
18
- import "./chunk-RBPMT53S.js";
19
- import "./chunk-BJYMTCWG.js";
20
- import "./chunk-VSHV7FEA.js";
16
+ } from "./chunk-2FHNY52R.js";
17
+ import "./chunk-VVRQQRMQ.js";
18
+ import "./chunk-4OFH4BNX.js";
19
+ import "./chunk-XQKUJL7H.js";
20
+ import "./chunk-MJEJQH5A.js";
21
+ import "./chunk-YNW2ZUUP.js";
21
22
  import {
22
23
  getHostEnvironment
23
24
  } from "./chunk-KDR2VAJP.js";
24
- import "./chunk-KBVH4XZC.js";
25
- import "./chunk-ABJ4G47X.js";
26
- import "./chunk-QNQNKIAA.js";
27
- import "./chunk-BHHUSBSD.js";
25
+ import "./chunk-6ZG7WNYX.js";
26
+ import "./chunk-N7YOS4ZU.js";
27
+ import "./chunk-422J3QRW.js";
28
+ import "./chunk-GBSDAD3N.js";
28
29
  export {
29
30
  browserSubmissionStore,
30
31
  cosmosChainList,
@@ -36,6 +37,7 @@ export {
36
37
  discoverSolanaWallets,
37
38
  evmSigner,
38
39
  getHostEnvironment,
40
+ memberTime,
39
41
  signInOptions,
40
42
  solanaSigner,
41
43
  telegramMiniAppInitData,
@@ -51,6 +51,26 @@ declare const budgetSchema: z.ZodObject<{
51
51
  }, z.core.$strict>]>;
52
52
  }, z.core.$strict>;
53
53
  type Budget = z.infer<typeof budgetSchema>;
54
+ /**
55
+ * A budget counted per tracker record author: the account that caused the record, such as a
56
+ * reaction's reactor, whether or not it belongs to a member. It caps what one person gives when a
57
+ * quest pays someone else. Only quests with a tracker trigger take one, in their `authorBudgets`.
58
+ */
59
+ declare const authorBudgetSchema: z.ZodObject<{
60
+ id: z.ZodString;
61
+ period: z.ZodEnum<{
62
+ lifetime: "lifetime";
63
+ day: "day";
64
+ week: "week";
65
+ month: "month";
66
+ }>;
67
+ limit: z.ZodNumber;
68
+ cost: z.ZodUnion<readonly [z.ZodNumber, z.ZodObject<{
69
+ balance: z.ZodString;
70
+ }, z.core.$strict>]>;
71
+ scope: z.ZodLiteral<"author">;
72
+ }, z.core.$strict>;
73
+ type AuthorBudget = z.infer<typeof authorBudgetSchema>;
54
74
  /**
55
75
  * One of the member's accepted, unrevoked quest completions, as `ctx.member.completions()` reads
56
76
  * it. `quest` is the quest's key and `key` the completion key. `completedAt` is when it was
@@ -100,12 +120,6 @@ type CapabilityErrorCode = KnownCapabilityErrorCode | (string & {});
100
120
  declare const capabilityFailureSchema: z.ZodObject<{
101
121
  code: z.ZodString;
102
122
  message: z.ZodString;
103
- /**
104
- * True when Relay retries the attempt if the error reaches it uncaught, and calls the provider
105
- * again. A failure that is not retryable is captured (or follows from the attempt's pinned
106
- * inputs), so every run of the attempt sees it again. A retryable failure that quest code
107
- * handles and moves past is final for the attempt; one that escapes the evaluation is retried.
108
- */
109
123
  retryable: z.ZodBoolean;
110
124
  }, z.core.$loose>;
111
125
  type CapabilityFailure = z.infer<typeof capabilityFailureSchema>;
@@ -142,4 +156,4 @@ declare class CapabilityError extends Error {
142
156
  static from(failure: CapabilityFailure): CapabilityError;
143
157
  }
144
158
 
145
- export { type Budget as B, CapabilityError as C, type KnownCapabilityErrorCode as K, type MemberCompletion as M, type CapabilityErrorCode as a, type CapabilityFailure as b, capabilityErrorCodes as c, budgetSchema as d, capabilityFailureSchema as e, completionKeySchema as f, completionPolicySchema as g, memberCompletionSchema as h, maxMemberCompletions as m };
159
+ export { type AuthorBudget as A, type Budget as B, CapabilityError as C, type KnownCapabilityErrorCode as K, type MemberCompletion as M, type CapabilityErrorCode as a, type CapabilityFailure as b, capabilityErrorCodes as c, authorBudgetSchema as d, budgetSchema as e, capabilityFailureSchema as f, completionKeySchema as g, completionPolicySchema as h, maxMemberCompletions as i, memberCompletionSchema as m };
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  createRelayClient
3
- } from "./chunk-NK6EER33.js";
3
+ } from "./chunk-VVRQQRMQ.js";
4
4
  import {
5
5
  RelayErrorCode,
6
6
  asRelayError,
7
7
  clientError,
8
8
  cosmosChain
9
- } from "./chunk-BHHUSBSD.js";
9
+ } from "./chunk-GBSDAD3N.js";
10
10
 
11
11
  // src/base58.ts
12
12
  var alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
@@ -520,6 +520,11 @@ function telegramMiniAppInitData() {
520
520
  return new URLSearchParams(hash.replace(/^#/, "")).get("tgWebAppData") || null;
521
521
  }
522
522
 
523
+ // src/member-time.ts
524
+ function memberTime(me, at = Date.now()) {
525
+ return at + (me.clock?.offsetMs ?? 0);
526
+ }
527
+
523
528
  // src/browser.ts
524
529
  function createBrowserRelayClient(options) {
525
530
  return createRelayClient({
@@ -699,6 +704,7 @@ export {
699
704
  readSignInMethods,
700
705
  signInOptions,
701
706
  telegramMiniAppInitData,
707
+ memberTime,
702
708
  createBrowserRelayClient,
703
709
  browserSubmissionStore
704
710
  };