@domino-sdk/relay 1.70.0 → 1.72.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/{accounts-B49TGZLk.d.ts → accounts-COLmXRbW.d.ts} +144 -11
  3. package/dist/{attempt-captures-Dn-oGE1o.d.ts → attempt-captures-CVl161qB.d.ts} +3 -2
  4. package/dist/authoring.d.ts +68 -25
  5. package/dist/authoring.js +12 -8
  6. package/dist/{automatic-outcomes-DeRyox-X.d.ts → automatic-outcomes-5l68PGr1.d.ts} +2 -2
  7. package/dist/browser.d.ts +9 -9
  8. package/dist/browser.js +11 -9
  9. package/dist/{catalog-CR_2iacf.d.ts → catalog-BR3g-1H9.d.ts} +41 -2
  10. package/dist/{chunk-NOQSKRSS.js → chunk-2UELTHW6.js} +12 -4
  11. package/dist/{chunk-SELJYCYY.js → chunk-3KKRXN5E.js} +1 -1
  12. package/dist/{chunk-4VDRNYUG.js → chunk-74SMLZZ5.js} +710 -677
  13. package/dist/{chunk-4BBDHTBF.js → chunk-ASBDB436.js} +1 -1
  14. package/dist/{chunk-3DUNFRKJ.js → chunk-BXUF3CRL.js} +32 -6
  15. package/dist/{chunk-BJ2W5ZVQ.js → chunk-CVJTIVAP.js} +1 -1
  16. package/dist/{chunk-FHOKCBTJ.js → chunk-ETGKC2SB.js} +1 -1
  17. package/dist/{chunk-XD6EUA27.js → chunk-FGZGL5PG.js} +1 -1
  18. package/dist/{chunk-OKKZPDCQ.js → chunk-GHBYWDEZ.js} +8 -1
  19. package/dist/{chunk-SDWG7CWQ.js → chunk-HN7DE2UN.js} +2 -2
  20. package/dist/{chunk-25WA4XYZ.js → chunk-I7XIBXT2.js} +74 -5
  21. package/dist/{chunk-UKUIE2ND.js → chunk-KIRXE37T.js} +6 -6
  22. package/dist/{chunk-VAGGGB6B.js → chunk-MDSSIOBC.js} +58 -1
  23. package/dist/{chunk-LZXDYSUH.js → chunk-PYZSCFMJ.js} +4 -0
  24. package/dist/{chunk-XZCTCSDG.js → chunk-QG6XVOOO.js} +153 -4
  25. package/dist/{chunk-2GVGZ7AN.js → chunk-TW4RABVS.js} +1 -1
  26. package/dist/{chunk-RYUM6X2K.js → chunk-UEVZ3TST.js} +29 -2
  27. package/dist/{chunk-HICAGUT5.js → chunk-VFHLMNYV.js} +1 -1
  28. package/dist/{chunk-RSZAYW3T.js → chunk-W6DBNBMT.js} +2 -2
  29. package/dist/{client-gJEheT2C.d.ts → client-B__hMWtK.d.ts} +104 -7
  30. package/dist/{dashboards-DZaB94sz.d.ts → dashboards-DXpjHnq-.d.ts} +3 -3
  31. package/dist/{deployments-QVGxC-fT.d.ts → deployments-CT2kQloT.d.ts} +199 -3
  32. package/dist/{identity-integration-BAJdzbdl.d.ts → identity-integration-ClX4oUAu.d.ts} +4 -4
  33. package/dist/index.d.ts +10 -10
  34. package/dist/index.js +7 -7
  35. package/dist/internal.d.ts +44 -26
  36. package/dist/internal.js +26 -50
  37. package/dist/{limits-UawUbr0S.d.ts → limits-B7wbnWhd.d.ts} +1 -1
  38. package/dist/{offers-0hqbnogq.d.ts → offers-D4pyeY9b.d.ts} +2 -2
  39. package/dist/portal-proxy.d.ts +2 -2
  40. package/dist/portal-proxy.js +10 -10
  41. package/dist/react/index.d.ts +31 -12
  42. package/dist/react/index.js +115 -41
  43. package/dist/{reward-deliveries-ARvt1UXb.d.ts → reward-deliveries-HGpj1VFz.d.ts} +1 -1
  44. package/dist/runtime/authoring.js +1 -1
  45. package/dist/runtime/chunks/A7G5P76B.js +1 -0
  46. package/dist/runtime/manifest.json +3 -3
  47. package/dist/runtime/schema.js +1 -1
  48. package/dist/schema.d.ts +40 -16
  49. package/dist/schema.js +7 -7
  50. package/dist/server/index.d.ts +12 -12
  51. package/dist/server/index.js +956 -576
  52. package/dist/{sign-in-providers-DCiufSGG.d.ts → sign-in-providers-lbOXCF8N.d.ts} +2 -2
  53. package/dist/solana.d.ts +12 -12
  54. package/dist/solana.js +8 -8
  55. package/dist/{telegram-browser-yx9WuNLX.d.ts → station-check-in-qBiaftfE.d.ts} +89 -7
  56. package/dist/{submission-input-C0DLv5Dj.d.ts → submission-input-U4aIkJuT.d.ts} +2 -2
  57. package/dist/telegram.d.ts +7 -7
  58. package/dist/testing.d.ts +15 -11
  59. package/dist/testing.js +23 -12
  60. package/dist/{tracker-data-CUopgomU.d.ts → tracker-data-2BYXZjsN.d.ts} +3 -3
  61. package/dist/{transport-e0uY1R7z.d.ts → transport-DcRXDZ1j.d.ts} +1838 -19
  62. package/dist/{wallet-CJTULM0Q.d.ts → wallet-BqswMAqZ.d.ts} +2 -2
  63. package/dist/{wallet-browser-DScvrvIj.d.ts → wallet-browser-B5r7u3xB.d.ts} +1 -1
  64. package/package.json +1 -1
  65. package/dist/runtime/chunks/447P2VLY.js +0 -1
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  clientIdentity,
3
3
  retryAfter
4
- } from "./chunk-FHOKCBTJ.js";
4
+ } from "./chunk-ETGKC2SB.js";
5
5
 
6
6
  // src/http-exchange.ts
7
7
  var uncertainStatuses = /* @__PURE__ */ (() => /* @__PURE__ */ new Set([500, 502, 504]))();
@@ -9,13 +9,13 @@ import {
9
9
  createHttpExchange,
10
10
  untilAborted,
11
11
  withQuery
12
- } from "./chunk-4BBDHTBF.js";
12
+ } from "./chunk-ASBDB436.js";
13
13
  import {
14
14
  PARTICIPANT_TIMEOUT,
15
15
  lifetime,
16
16
  retrying,
17
17
  validTimeout
18
- } from "./chunk-FHOKCBTJ.js";
18
+ } from "./chunk-ETGKC2SB.js";
19
19
  import {
20
20
  authProvidersSchema,
21
21
  collectionPassSchema,
@@ -34,7 +34,7 @@ import {
34
34
  questOutcomeSchema,
35
35
  rewardDeliveriesSchema,
36
36
  rewardDeliveryQuerySchema
37
- } from "./chunk-SELJYCYY.js";
37
+ } from "./chunk-3KKRXN5E.js";
38
38
  import {
39
39
  exchangeResultSchema,
40
40
  exchangeSchema,
@@ -44,7 +44,7 @@ import {
44
44
  participantSessionSchema,
45
45
  questExperienceSchema,
46
46
  sessionMember
47
- } from "./chunk-2GVGZ7AN.js";
47
+ } from "./chunk-TW4RABVS.js";
48
48
  import {
49
49
  engagementBoundaryPageSchema,
50
50
  engagementPageQuerySchema,
@@ -55,7 +55,7 @@ import {
55
55
  referralDefinitionSchema,
56
56
  referralHistorySchema,
57
57
  referralSummarySchema
58
- } from "./chunk-XD6EUA27.js";
58
+ } from "./chunk-FGZGL5PG.js";
59
59
  import {
60
60
  AVATAR_UPLOAD_LIMIT,
61
61
  accountConnectionSchema,
@@ -99,6 +99,7 @@ import {
99
99
  quizEvidenceSchema,
100
100
  signInAccountSchema,
101
101
  signInProviderInputSchema,
102
+ stationCheckInSchema,
102
103
  submissionEvidenceSchema,
103
104
  submitSchema,
104
105
  telegramAccountConnectionSchema,
@@ -113,7 +114,7 @@ import {
113
114
  walletTransactionChallengeSchema,
114
115
  walletTransactionProofSchema,
115
116
  walletUnlinkInputSchema
116
- } from "./chunk-4VDRNYUG.js";
117
+ } from "./chunk-74SMLZZ5.js";
117
118
  import {
118
119
  RelayError,
119
120
  RelayErrorCode,
@@ -1697,6 +1698,31 @@ function relayClient(options) {
1697
1698
  operationId: body2.actionId
1698
1699
  });
1699
1700
  },
1701
+ /**
1702
+ * Checks the signed-in member in at a quest's code station with the code they were given,
1703
+ * and resolves with the queued attempt, which the quest decides with `{ kind:
1704
+ * "station-code", reference: station }` in `ctx.action`; a repeat with the same `actionId`
1705
+ * resolves with the first attempt. Refusals: 422 `station-unknown` when the quest has no
1706
+ * such station, 422 `station-proof-mismatch` when transactions prove it, 409
1707
+ * `station-code-not-set` while it has no code in this environment, 409 `station-revoked`,
1708
+ * 409 `station-closed` outside its window, 422 `station-code-invalid` for a wrong code, and
1709
+ * 429 `rate-limited` (with `Retry-After`) after 10 wrong codes from the member at the station
1710
+ * in an hour or 600 at the station in 10 minutes, right codes included until it ends.
1711
+ *
1712
+ * @experimental A minor release can change check-in stations.
1713
+ */
1714
+ checkIn: async (quest, station, value, requestOptions) => {
1715
+ const body2 = parseInput(stationCheckInSchema, withActionId(value));
1716
+ return request(
1717
+ `/v1/me/quests/${parseInput(identifier, quest)}/stations/${parseInput(identifier, station)}/check-in`,
1718
+ attemptSchema,
1719
+ {
1720
+ json: body2,
1721
+ options: requestOptions,
1722
+ operationId: body2.actionId
1723
+ }
1724
+ );
1725
+ },
1700
1726
  /**
1701
1727
  * Why automatic quests did or did not run for the signed-in member's activity, newest first:
1702
1728
  * each admission, and each skip with its stable code.
@@ -3,7 +3,7 @@ import {
3
3
  limits,
4
4
  resourceHandle,
5
5
  responseShape
6
- } from "./chunk-4VDRNYUG.js";
6
+ } from "./chunk-74SMLZZ5.js";
7
7
  import {
8
8
  parseDefinition
9
9
  } from "./chunk-VNEJH4NT.js";
@@ -4,7 +4,7 @@ import {
4
4
 
5
5
  // package.json
6
6
  var name = "@domino-sdk/relay";
7
- var version = "1.70.0";
7
+ var version = "1.72.0";
8
8
 
9
9
  // src/client-identity.ts
10
10
  function clientIdentity() {
@@ -12,7 +12,7 @@ import {
12
12
  resourceHandle,
13
13
  responseShape,
14
14
  tierRewardSchema
15
- } from "./chunk-4VDRNYUG.js";
15
+ } from "./chunk-74SMLZZ5.js";
16
16
  import {
17
17
  parseDefinition
18
18
  } from "./chunk-VNEJH4NT.js";
@@ -9,7 +9,7 @@ import {
9
9
  rewardBundleSchema,
10
10
  settingsValuesSchema,
11
11
  trackerTriggerContextSchema
12
- } from "./chunk-4VDRNYUG.js";
12
+ } from "./chunk-74SMLZZ5.js";
13
13
 
14
14
  // src/server/attempt-captures.ts
15
15
  import * as z from "zod";
@@ -65,6 +65,13 @@ var attemptCaptureSchema = /* @__PURE__ */ (() => z.object({
65
65
  * @experimental A minor release can change quest actions.
66
66
  */
67
67
  action: attemptActionSchema.nullable().optional(),
68
+ /**
69
+ * The code station the member checked in at, for an attempt a station's code started: its
70
+ * `ctx.action` is `{ kind: "station-code", reference: station }`. Absent for any other attempt.
71
+ *
72
+ * @experimental A minor release can change check-in stations.
73
+ */
74
+ station: z.string().optional(),
68
75
  eligibleAt: timestamp,
69
76
  calendar: z.object({
70
77
  segments: z.array(
@@ -4,10 +4,10 @@ import {
4
4
  imageFieldsSchema,
5
5
  imageInspectionSchema,
6
6
  imageSightingsSchema
7
- } from "./chunk-HICAGUT5.js";
7
+ } from "./chunk-VFHLMNYV.js";
8
8
  import {
9
9
  photoResultSchema
10
- } from "./chunk-4VDRNYUG.js";
10
+ } from "./chunk-74SMLZZ5.js";
11
11
 
12
12
  // src/image-results.ts
13
13
  import * as z from "zod";
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  imageAssetArtifactSchema
3
- } from "./chunk-HICAGUT5.js";
3
+ } from "./chunk-VFHLMNYV.js";
4
4
  import {
5
5
  authScopeSchema,
6
6
  exchangeResultSchema
7
- } from "./chunk-2GVGZ7AN.js";
7
+ } from "./chunk-TW4RABVS.js";
8
8
  import {
9
9
  appIdentityKindSchema,
10
10
  cosmosAddressSchema,
@@ -17,7 +17,7 @@ import {
17
17
  openIdentityKindSchema,
18
18
  pageCursorSchema,
19
19
  solanaAddressSchema
20
- } from "./chunk-4VDRNYUG.js";
20
+ } from "./chunk-74SMLZZ5.js";
21
21
 
22
22
  // src/credential-secrets.ts
23
23
  import * as z from "zod";
@@ -1117,7 +1117,43 @@ var customDomainListSchema = /* @__PURE__ */ (() => z5.object({
1117
1117
  }))();
1118
1118
  var customDomainInputSchema = /* @__PURE__ */ (() => z5.object({ hostname: z5.string().min(1).max(300) }).strict())();
1119
1119
  var stagingAccessModeSchema = /* @__PURE__ */ (() => z5.enum(["console", "password"]))();
1120
- var stagingAccessSchema = /* @__PURE__ */ (() => z5.object({ mode: stagingAccessModeSchema }))();
1120
+ var stagingOrigin = "https://staging.invalid";
1121
+ var reservedStagingPaths = ["/__domino", "/relay", "/.well-known"];
1122
+ var stagingServerPathSchema = /* @__PURE__ */ (() => z5.string().max(200).refine((path) => {
1123
+ if (!path.startsWith("/") || path.startsWith("//") || /[\\?#]/.test(path) || // oxlint-disable-next-line no-control-regex
1124
+ /[\u0000-\u0020\u007f]/.test(path)) {
1125
+ return false;
1126
+ }
1127
+ try {
1128
+ return new URL(path, stagingOrigin).pathname === path;
1129
+ } catch {
1130
+ return false;
1131
+ }
1132
+ }, "Expected a path such as /api/, without a query or dot segments").refine(
1133
+ (path) => !reservedStagingPaths.some(
1134
+ (reserved) => reserved.startsWith(path) || path.startsWith(reserved)
1135
+ ),
1136
+ "Server paths cannot be / or cover /__domino, /relay or /.well-known"
1137
+ ))();
1138
+ var stagingServerAccessSchema = /* @__PURE__ */ (() => z5.object({
1139
+ paths: z5.array(z5.string())
1140
+ }))();
1141
+ var stagingAccessSchema = /* @__PURE__ */ (() => z5.object({
1142
+ mode: stagingAccessModeSchema,
1143
+ /**
1144
+ * Paths servers may call with a staging server key. Absent from older servers, which means off.
1145
+ *
1146
+ * @experimental A minor release can change staging server access.
1147
+ */
1148
+ server: stagingServerAccessSchema.optional()
1149
+ }))();
1150
+ var stagingServerAccessInputSchema = /* @__PURE__ */ (() => z5.object({
1151
+ // Each request on a server path is checked against every prefix; an app needs a few.
1152
+ paths: z5.array(stagingServerPathSchema).max(20).refine(
1153
+ (paths) => new Set(paths).size === paths.length,
1154
+ "Each server path can be listed once"
1155
+ )
1156
+ }).strict())();
1121
1157
  var stagingAccessInputSchema = /* @__PURE__ */ (() => z5.discriminatedUnion("mode", [
1122
1158
  z5.object({ mode: z5.literal("console") }).strict(),
1123
1159
  z5.object({
@@ -1125,7 +1161,33 @@ var stagingAccessInputSchema = /* @__PURE__ */ (() => z5.discriminatedUnion("mod
1125
1161
  password: z5.string().min(8).max(128)
1126
1162
  }).strict()
1127
1163
  ]))();
1128
- var stagingOrigin = "https://staging.invalid";
1164
+ var stagingAccessChangeSchema = /* @__PURE__ */ (() => z5.union([
1165
+ z5.object({
1166
+ mode: z5.literal("console"),
1167
+ server: stagingServerAccessInputSchema.optional()
1168
+ }).strict(),
1169
+ z5.object({
1170
+ mode: z5.literal("password"),
1171
+ password: z5.string().min(8).max(128),
1172
+ server: stagingServerAccessInputSchema.optional()
1173
+ }).strict(),
1174
+ z5.object({ server: stagingServerAccessInputSchema }).strict()
1175
+ ]))();
1176
+ var stagingServerKeySchema = /* @__PURE__ */ (() => z5.object({
1177
+ id: z5.string(),
1178
+ name: z5.string(),
1179
+ lastFour: z5.string(),
1180
+ createdAt: z5.number(),
1181
+ lastUsedAt: z5.number().nullable()
1182
+ }))();
1183
+ var stagingServerKeyListSchema = /* @__PURE__ */ (() => z5.object({
1184
+ items: z5.array(stagingServerKeySchema),
1185
+ nextCursor: z5.null()
1186
+ }))();
1187
+ var stagingServerKeyInputSchema = /* @__PURE__ */ (() => z5.object({ name: z5.string().trim().min(1).max(80) }).strict())();
1188
+ var stagingServerKeyCreatedSchema = /* @__PURE__ */ (() => stagingServerKeySchema.extend({
1189
+ key: z5.string()
1190
+ }))();
1129
1191
  var stagingPathSchema = /* @__PURE__ */ (() => z5.string().max(2048).refine((path) => {
1130
1192
  if (!path.startsWith("/") || path.startsWith("//") || path.includes("\\") || // oxlint-disable-next-line no-control-regex
1131
1193
  /[\u0000-\u001f\u007f]/.test(path)) {
@@ -1524,8 +1586,15 @@ export {
1524
1586
  customDomainListSchema,
1525
1587
  customDomainInputSchema,
1526
1588
  stagingAccessModeSchema,
1589
+ stagingServerPathSchema,
1590
+ stagingServerAccessSchema,
1527
1591
  stagingAccessSchema,
1528
1592
  stagingAccessInputSchema,
1593
+ stagingAccessChangeSchema,
1594
+ stagingServerKeySchema,
1595
+ stagingServerKeyListSchema,
1596
+ stagingServerKeyInputSchema,
1597
+ stagingServerKeyCreatedSchema,
1529
1598
  stagingPathSchema,
1530
1599
  stagingLinkSchema,
1531
1600
  buildSnapshotSchema,
@@ -6,13 +6,13 @@ import {
6
6
  imageSightingsSchema,
7
7
  imageUploadsSchema,
8
8
  publishedImageSchema
9
- } from "./chunk-HICAGUT5.js";
9
+ } from "./chunk-VFHLMNYV.js";
10
10
  import {
11
11
  dashboardArtifactSchema,
12
12
  dashboardIssue,
13
13
  dashboardPreviewSchema,
14
14
  normalizeDashboard
15
- } from "./chunk-BJ2W5ZVQ.js";
15
+ } from "./chunk-CVJTIVAP.js";
16
16
  import {
17
17
  authProvidersSchema,
18
18
  collectionPassSchema,
@@ -23,7 +23,7 @@ import {
23
23
  questOutcomePageSchema,
24
24
  questOutcomeSchema,
25
25
  rewardDeliveriesSchema
26
- } from "./chunk-SELJYCYY.js";
26
+ } from "./chunk-3KKRXN5E.js";
27
27
  import {
28
28
  catalogDeploymentSchema,
29
29
  collectionViewSchema,
@@ -37,7 +37,7 @@ import {
37
37
  questExperienceSchema,
38
38
  questTypeVersionSchema,
39
39
  questViewSchema
40
- } from "./chunk-2GVGZ7AN.js";
40
+ } from "./chunk-TW4RABVS.js";
41
41
  import {
42
42
  engagementArtifactSchema,
43
43
  engagementBoundaryPageSchema,
@@ -52,7 +52,7 @@ import {
52
52
  referralDefinitionSchema,
53
53
  referralHistorySchema,
54
54
  referralSummarySchema
55
- } from "./chunk-XD6EUA27.js";
55
+ } from "./chunk-FGZGL5PG.js";
56
56
  import {
57
57
  accountConnectionSchema,
58
58
  attemptSchema,
@@ -120,7 +120,7 @@ import {
120
120
  walletTransactionChallengeSchema,
121
121
  walletTransactionsSchema,
122
122
  whereSettings
123
- } from "./chunk-4VDRNYUG.js";
123
+ } from "./chunk-74SMLZZ5.js";
124
124
 
125
125
  // src/deployments.ts
126
126
  import * as z from "zod";
@@ -77,11 +77,68 @@ function getHostEnvironment() {
77
77
  return pending ??= readHostEnvironment();
78
78
  }
79
79
 
80
+ // src/station-qr.ts
81
+ function stationPayLink(url, station) {
82
+ const target = new URL(url);
83
+ target.searchParams.set("station", station);
84
+ return `solana:${encodeURIComponent(target.href)}`;
85
+ }
86
+ function stationCodeLink(url, { quest, station, code }) {
87
+ const target = new URL(url);
88
+ target.searchParams.set("quest", quest);
89
+ target.searchParams.set("station", station);
90
+ target.searchParams.set("code", code);
91
+ return target.href;
92
+ }
93
+ function parseStationCodeLink(link) {
94
+ let params;
95
+ try {
96
+ params = new URL(link).searchParams;
97
+ } catch {
98
+ return null;
99
+ }
100
+ const quest = params.get("quest");
101
+ const station = params.get("station");
102
+ const code = params.get("code");
103
+ return quest && station && code ? { quest, station, code } : null;
104
+ }
105
+ var escapeXml = (text) => text.replace(
106
+ /[&<>"']/g,
107
+ (character) => ({
108
+ "&": "&amp;",
109
+ "<": "&lt;",
110
+ ">": "&gt;",
111
+ '"': "&quot;",
112
+ "'": "&apos;"
113
+ })[character] ?? character
114
+ );
115
+ async function stationQrSvg(link, label) {
116
+ const { encodeQR } = await import("qr");
117
+ const modules = encodeQR(link, "raw", { ecc: "medium", border: 4 });
118
+ const size = modules.length;
119
+ const scale = 10;
120
+ const width = size * scale;
121
+ const labelHeight = 6 * scale;
122
+ const path = modules.flatMap(
123
+ (row, y) => row.flatMap((dark, x) => dark ? [`M${x} ${y}h1v1h-1z`] : [])
124
+ ).join("");
125
+ return `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${width + labelHeight}" viewBox="0 0 ${width} ${width + labelHeight}">
126
+ <rect width="100%" height="100%" fill="#fff"/>
127
+ <path transform="scale(${scale})" fill="#000" shape-rendering="crispEdges" d="${path}"/>
128
+ <text x="${width / 2}" y="${width + labelHeight / 2}" font-family="sans-serif" font-size="${2.4 * scale}" text-anchor="middle" dominant-baseline="middle" fill="#000">${escapeXml(label)}</text>
129
+ </svg>
130
+ `;
131
+ }
132
+
80
133
  export {
81
134
  noAccount,
82
135
  registeredWallets,
83
136
  connectSolanaAccount,
84
137
  hostEnvironmentPath,
85
138
  hostEnvironmentSchema,
86
- getHostEnvironment
139
+ getHostEnvironment,
140
+ stationPayLink,
141
+ stationCodeLink,
142
+ parseStationCodeLink,
143
+ stationQrSvg
87
144
  };
@@ -32,6 +32,10 @@ var participantRoutes = [
32
32
  { method: "POST", path: `/v1/attempts/:attempt${id}/retry` },
33
33
  { method: "GET", path: `/v1/me/quests/:quest${id}/submission` },
34
34
  { method: "POST", path: `/v1/me/quests/:quest${id}/submission` },
35
+ {
36
+ method: "POST",
37
+ path: `/v1/me/quests/:quest${id}/stations/:station${id}/check-in`
38
+ },
35
39
  { method: "GET", path: `/v1/me/submissions/:submission${id}` },
36
40
  { method: "POST", path: `/v1/me/submissions/:submission${id}` },
37
41
  { method: "POST", path: `/v1/me/submissions/:submission${id}/submit` },
@@ -1,19 +1,24 @@
1
1
  import {
2
2
  createRelayClient
3
- } from "./chunk-3DUNFRKJ.js";
3
+ } from "./chunk-BXUF3CRL.js";
4
4
  import {
5
5
  connectSolanaAccount,
6
6
  noAccount,
7
+ parseStationCodeLink,
7
8
  registeredWallets
8
- } from "./chunk-VAGGGB6B.js";
9
+ } from "./chunk-MDSSIOBC.js";
10
+ import {
11
+ sessionMember
12
+ } from "./chunk-TW4RABVS.js";
9
13
  import {
10
14
  base58,
11
15
  cosmosChain
12
- } from "./chunk-4VDRNYUG.js";
16
+ } from "./chunk-74SMLZZ5.js";
13
17
  import {
14
18
  RelayErrorCode,
15
19
  asRelayError,
16
- clientError
20
+ clientError,
21
+ isRelayError
17
22
  } from "./chunk-VNEJH4NT.js";
18
23
 
19
24
  // src/wallet-browser.ts
@@ -515,6 +520,141 @@ function memberTime(me, at = Date.now()) {
515
520
  return at + (me.clock?.offsetMs ?? 0);
516
521
  }
517
522
 
523
+ // src/refusal.ts
524
+ function isRefusal(cause) {
525
+ return isRelayError(cause) && cause.kind === "http" && !cause.uncertain && cause.status !== void 0 && cause.status >= 400 && cause.status < 500;
526
+ }
527
+
528
+ // src/session-items.ts
529
+ function readSessionItem(key) {
530
+ try {
531
+ return window.sessionStorage.getItem(key);
532
+ } catch {
533
+ return null;
534
+ }
535
+ }
536
+ function writeSessionItem(key, value) {
537
+ try {
538
+ if (value === null) {
539
+ window.sessionStorage.removeItem(key);
540
+ } else {
541
+ window.sessionStorage.setItem(key, value);
542
+ }
543
+ } catch {
544
+ }
545
+ }
546
+ function readSessionJson(key, valid) {
547
+ try {
548
+ const value = JSON.parse(readSessionItem(key) ?? "null");
549
+ return valid(value) ? value : null;
550
+ } catch {
551
+ return null;
552
+ }
553
+ }
554
+
555
+ // src/station-check-in.ts
556
+ var PENDING = "domino:pending-station-check-in";
557
+ var passing = /* @__PURE__ */ (() => /* @__PURE__ */ new Set(["rate-limited", "attempt-pending"]))();
558
+ var stored = () => readSessionJson(
559
+ PENDING,
560
+ (value) => typeof value === "object" && value !== null && ["quest", "station", "code", "actionId"].every(
561
+ (key) => typeof value[key] === "string"
562
+ )
563
+ );
564
+ function captureStationCheckIn() {
565
+ if (typeof window === "undefined") {
566
+ return null;
567
+ }
568
+ const url = new URL(window.location.href);
569
+ const linked = parseStationCodeLink(url);
570
+ if (!linked) {
571
+ return stored();
572
+ }
573
+ const kept = stored();
574
+ const pending = kept && kept.quest === linked.quest && kept.station === linked.station && kept.code === linked.code ? kept : { ...linked, actionId: crypto.randomUUID() };
575
+ writeSessionItem(PENDING, JSON.stringify(pending));
576
+ url.searchParams.delete("code");
577
+ window.history.replaceState(window.history.state, "", url);
578
+ return pending;
579
+ }
580
+ function stationCheckInRetryable(state) {
581
+ return state.status === "failed" || state.status === "refused" && passing.has(state.code);
582
+ }
583
+ function forgetStationCheckIn(pending) {
584
+ if (stored()?.actionId === pending.actionId) {
585
+ writeSessionItem(PENDING, null);
586
+ }
587
+ }
588
+ function checkInStation(pending, options = {}) {
589
+ return {
590
+ key: pending.station,
591
+ label: options.stations?.find((station) => station.key === pending.station)?.label ?? pending.station
592
+ };
593
+ }
594
+ async function sendStationCheckIn(relay, pending, options = {}) {
595
+ const where = {
596
+ quest: pending.quest,
597
+ station: checkInStation(pending, options)
598
+ };
599
+ try {
600
+ const attempt = await relay.quests.checkIn(
601
+ pending.quest,
602
+ pending.station,
603
+ { code: pending.code, actionId: pending.actionId },
604
+ options.session ? { session: options.session } : void 0
605
+ );
606
+ forgetStationCheckIn(pending);
607
+ return { status: "checked-in", ...where, attempt };
608
+ } catch (caught) {
609
+ const error = asRelayError(caught, "The check-in couldn't be sent.");
610
+ if (error.status === 401 || error.code === "stale-session") {
611
+ return { status: "sign-in-required", ...where };
612
+ }
613
+ if (!isRefusal(caught)) {
614
+ return { status: "failed", ...where, error };
615
+ }
616
+ const code = error.code ?? (error.status === 429 ? "rate-limited" : "");
617
+ if (!passing.has(code)) {
618
+ forgetStationCheckIn(pending);
619
+ }
620
+ return {
621
+ status: "refused",
622
+ ...where,
623
+ code,
624
+ error,
625
+ ...error.retryAfter === void 0 ? {} : { retryAfter: error.retryAfter }
626
+ };
627
+ }
628
+ }
629
+ async function checkInAtStation(relay, options = {}) {
630
+ const pending = captureStationCheckIn();
631
+ if (!pending) {
632
+ return { status: "none" };
633
+ }
634
+ let session;
635
+ try {
636
+ session = await relay.auth.session();
637
+ } catch (caught) {
638
+ return {
639
+ status: "failed",
640
+ quest: pending.quest,
641
+ station: checkInStation(pending, options),
642
+ error: asRelayError(caught, "Couldn't read who is signed in.")
643
+ };
644
+ }
645
+ if (!sessionMember(session)) {
646
+ return {
647
+ status: "sign-in-required",
648
+ quest: pending.quest,
649
+ station: checkInStation(pending, options)
650
+ };
651
+ }
652
+ return sendStationCheckIn(relay, pending, {
653
+ ...options,
654
+ session: session.id
655
+ });
656
+ }
657
+
518
658
  // src/browser.ts
519
659
  function createBrowserRelayClient(options) {
520
660
  return createRelayClient({
@@ -694,6 +834,15 @@ export {
694
834
  readSignInMethods,
695
835
  signInOptions,
696
836
  memberTime,
837
+ isRefusal,
838
+ readSessionItem,
839
+ writeSessionItem,
840
+ readSessionJson,
841
+ captureStationCheckIn,
842
+ stationCheckInRetryable,
843
+ checkInStation,
844
+ sendStationCheckIn,
845
+ checkInAtStation,
697
846
  createBrowserRelayClient,
698
847
  browserSubmissionStore
699
848
  };
@@ -19,7 +19,7 @@ import {
19
19
  storedQuestDescriptionSchema,
20
20
  storedReviewModeSchema,
21
21
  tieredRewardReferenceSchema
22
- } from "./chunk-4VDRNYUG.js";
22
+ } from "./chunk-74SMLZZ5.js";
23
23
 
24
24
  // src/participant-activity.ts
25
25
  import * as z from "zod";
@@ -2,13 +2,22 @@ import {
2
2
  discordMessageDataSchema,
3
3
  discordMessageTextDataSchema,
4
4
  discordReactionDataSchema,
5
+ galleryKinds,
5
6
  isKnownTrackerSource,
6
7
  takesSolanaTransaction,
7
8
  trackerDataSchema,
8
9
  xAccountRoles
9
- } from "./chunk-4VDRNYUG.js";
10
+ } from "./chunk-74SMLZZ5.js";
10
11
 
11
12
  // src/quest-shape.ts
13
+ var QuestShapeError = class extends Error {
14
+ constructor(message, code) {
15
+ super(message);
16
+ this.code = code;
17
+ this.name = "QuestShapeError";
18
+ }
19
+ code;
20
+ };
12
21
  function validateQuestShape(description, options = {}) {
13
22
  const {
14
23
  trigger,
@@ -18,7 +27,8 @@ function validateQuestShape(description, options = {}) {
18
27
  retryCooldownMs,
19
28
  completionCooldownMs,
20
29
  authorBudgets = [],
21
- stations
30
+ stations,
31
+ gallery
22
32
  } = description;
23
33
  const tracker = trigger.kind === "automatic" ? trigger.tracker : void 0;
24
34
  const content = tracker?.content === true;
@@ -67,6 +77,22 @@ function validateQuestShape(description, options = {}) {
67
77
  "Stations are for quests a signed Solana transaction completes: a member-submitted manual() quest without input"
68
78
  );
69
79
  }
80
+ if (gallery && options.template) {
81
+ throw new Error(
82
+ "Reusable quest types cannot declare a photo gallery: declare it on a quest written in code"
83
+ );
84
+ }
85
+ if (gallery && !options.authoring && !(trigger.kind === "manual" && trigger.input === "photo")) {
86
+ throw new QuestShapeError(
87
+ "A photo gallery is for a quest whose input is a photo: manual({ input: evidence.photo() })",
88
+ "gallery-requires-photo"
89
+ );
90
+ }
91
+ if (gallery && !galleryKinds.some((kind) => kind === gallery.kind)) {
92
+ throw new Error(
93
+ `Unknown gallery kind "${gallery.kind}": use ${galleryKinds.map((kind) => `"${kind}"`).join(" or ")}`
94
+ );
95
+ }
70
96
  if (trigger.kind === "automatic" && !tracker) {
71
97
  if (!options.template && requires.length === 0) {
72
98
  throw new Error("Automatic quests need at least one prerequisite");
@@ -120,6 +146,7 @@ function sourceDataSchema(source) {
120
146
  }
121
147
 
122
148
  export {
149
+ QuestShapeError,
123
150
  validateQuestShape,
124
151
  sourceRoles,
125
152
  sourceDataSchema
@@ -2,7 +2,7 @@ import {
2
2
  identifier,
3
3
  responseShape,
4
4
  xTweetSchema
5
- } from "./chunk-4VDRNYUG.js";
5
+ } from "./chunk-74SMLZZ5.js";
6
6
 
7
7
  // src/x.ts
8
8
  import * as z from "zod";