@domino-sdk/relay 0.27.0 → 0.29.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/dist/browser.js CHANGED
@@ -1,27 +1,33 @@
1
1
  import {
2
2
  browserSubmissionStore,
3
+ cosmosChainList,
3
4
  cosmosSigner,
4
5
  createBrowserRelayClient,
5
6
  discoverCosmosWallets,
6
7
  discoverEvmWallets,
8
+ discoverSignInWallets,
7
9
  discoverSolanaWallets,
8
10
  evmSigner,
11
+ signInOptions,
9
12
  solanaSigner,
10
13
  walletStandardSolanaSigner
11
- } from "./chunk-RVGO2CRA.js";
12
- import "./chunk-D6AIUNSM.js";
13
- import "./chunk-AKB266O5.js";
14
- import "./chunk-M3R5V5WC.js";
15
- import "./chunk-D6BX627V.js";
16
- import "./chunk-IXLY3A7B.js";
14
+ } from "./chunk-MVCKCDNR.js";
15
+ import "./chunk-5LLU7UUV.js";
16
+ import "./chunk-YKS6P4IP.js";
17
+ import "./chunk-LAKQCIHX.js";
18
+ import "./chunk-MRKFRCCI.js";
19
+ import "./chunk-BE5V6RFD.js";
17
20
  export {
18
21
  browserSubmissionStore,
22
+ cosmosChainList,
19
23
  cosmosSigner,
20
24
  createBrowserRelayClient,
21
25
  discoverCosmosWallets,
22
26
  discoverEvmWallets,
27
+ discoverSignInWallets,
23
28
  discoverSolanaWallets,
24
29
  evmSigner,
30
+ signInOptions,
25
31
  solanaSigner,
26
32
  walletStandardSolanaSigner
27
33
  };
@@ -8,6 +8,7 @@ import {
8
8
  leaderboardArtifactSchema,
9
9
  leaderboardDefinitionSchema,
10
10
  leaderboardPageSchema,
11
+ leaderboardPlacementSchema,
11
12
  leaderboardPreviewSchema,
12
13
  leaderboardQuerySchema,
13
14
  normalizeAuthoringIdentity,
@@ -18,7 +19,7 @@ import {
18
19
  referralHistorySchema,
19
20
  referralSummarySchema,
20
21
  validateAuthoringIdentity
21
- } from "./chunk-AKB266O5.js";
22
+ } from "./chunk-YKS6P4IP.js";
22
23
  import {
23
24
  authScopeSchema,
24
25
  exchangeResultSchema,
@@ -35,14 +36,17 @@ import {
35
36
  walletSignInNetworksSchema,
36
37
  walletSignatureSchema,
37
38
  walletUnlinkInputSchema
38
- } from "./chunk-M3R5V5WC.js";
39
+ } from "./chunk-LAKQCIHX.js";
39
40
  import {
40
41
  AVATAR_UPLOAD_LIMIT,
41
42
  avatarUploadTypes,
42
43
  ownProfileSchema,
43
- profileUpdateSchema,
44
- publicProfileSchema
45
- } from "./chunk-D6BX627V.js";
44
+ profileCompletionPageSchema,
45
+ profileCompletionQuerySchema,
46
+ profileReferralSchema,
47
+ profileSummarySchema,
48
+ profileUpdateSchema
49
+ } from "./chunk-MRKFRCCI.js";
46
50
  import {
47
51
  accountConnectionSchema,
48
52
  attemptSchema,
@@ -81,7 +85,7 @@ import {
81
85
  validateSubmissionValue,
82
86
  valueEvidenceSchema,
83
87
  xTweetSchema
84
- } from "./chunk-IXLY3A7B.js";
88
+ } from "./chunk-BE5V6RFD.js";
85
89
 
86
90
  // src/point-ledgers.ts
87
91
  import { z } from "zod";
@@ -1871,7 +1875,16 @@ function createRelayClient(options) {
1871
1875
  query(`/v1/leaderboards/${identifier.parse(board)}`, parsed),
1872
1876
  leaderboardPageSchema
1873
1877
  );
1874
- }
1878
+ },
1879
+ /**
1880
+ * A profile's current rank and score on `board` (`profile.id` from a leaderboard row or
1881
+ * `profiles.mine()`). Needs the board's access, like `standings`; a profile this viewer
1882
+ * cannot see is a 404, as in `profiles.get`.
1883
+ */
1884
+ placement: (board, profile) => request(
1885
+ `/v1/leaderboards/${identifier.parse(board)}/profiles/${identifier.parse(profile)}`,
1886
+ leaderboardPlacementSchema
1887
+ )
1875
1888
  },
1876
1889
  /**
1877
1890
  * Participant profiles: the display name and avatar other participants see where the project
@@ -1916,12 +1929,31 @@ function createRelayClient(options) {
1916
1929
  });
1917
1930
  },
1918
1931
  /**
1919
- * A profile page by its public ID (`profile.id` from a leaderboard row or `mine()`). A
1920
- * profile that is missing, hidden or not visible to this viewer is a 404.
1932
+ * A profile's name and avatar by its public ID (`profile.id` from a leaderboard row or
1933
+ * `mine()`). A profile that is missing, hidden or not visible to this viewer is a 404.
1921
1934
  */
1922
1935
  get: (profile) => request(
1923
1936
  `/v1/profiles/${identifier.parse(profile)}`,
1924
- publicProfileSchema
1937
+ profileSummarySchema
1938
+ ),
1939
+ /**
1940
+ * A page of the profile's completions of quests that show on profiles, most recently
1941
+ * completed first. Pass the page's `nextCursor` as `cursor` for the next one.
1942
+ */
1943
+ completions: (profile, options2 = {}) => request(
1944
+ query(
1945
+ `/v1/profiles/${identifier.parse(profile)}/completions`,
1946
+ profileCompletionQuerySchema.parse(options2)
1947
+ ),
1948
+ profileCompletionPageSchema
1949
+ ),
1950
+ /**
1951
+ * The profile's invited and qualified counts and milestones in one referral program. Needs
1952
+ * a signed-in participant, as referral programs do.
1953
+ */
1954
+ referral: (profile, program) => request(
1955
+ `/v1/profiles/${identifier.parse(profile)}/referrals/${identifier.parse(program)}`,
1956
+ profileReferralSchema
1925
1957
  )
1926
1958
  },
1927
1959
  quests: {
@@ -1119,6 +1119,7 @@ var questPresentationSchema = z13.object({
1119
1119
  }).strict().optional()
1120
1120
  }).strict().optional()
1121
1121
  }).strict();
1122
+ var questProfileSchema = z13.object({ visible: z13.boolean() }).strict();
1122
1123
  var questDescriptionSchema = z13.object({
1123
1124
  quest: identifier,
1124
1125
  runtimeVersion: z13.union([z13.literal(1), z13.literal(2)]).default(1),
@@ -1134,6 +1135,12 @@ var questDescriptionSchema = z13.object({
1134
1135
  requires: z13.array(prerequisiteSchema).max(30).default([]),
1135
1136
  completion: completionPolicySchema,
1136
1137
  visibility: z13.enum(["visible", "hidden"]).default("visible"),
1138
+ /**
1139
+ * Whether completions show on participant profiles (`/v1/profiles/:id/completions`). Absent
1140
+ * is hidden. Optional, not defaulted: releases carry the key only when the author sets it, so
1141
+ * clients and pods that predate it (strict release schemas) still read every other release.
1142
+ */
1143
+ profile: questProfileSchema.optional(),
1137
1144
  budgets: z13.array(budgetSchema).max(20).default([])
1138
1145
  }).strict();
1139
1146
  var artifactSchema = z13.object({ code: z13.string().min(1).max(1e6) }).strict();
@@ -1626,6 +1633,7 @@ export {
1626
1633
  rewardBundleSchema,
1627
1634
  mediaUrlSchema,
1628
1635
  questPresentationSchema,
1636
+ questProfileSchema,
1629
1637
  questDescriptionSchema,
1630
1638
  artifactSchema,
1631
1639
  releaseSchema,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  identifier
3
- } from "./chunk-IXLY3A7B.js";
3
+ } from "./chunk-BE5V6RFD.js";
4
4
 
5
5
  // src/auth.ts
6
6
  import { z } from "zod";
@@ -72,6 +72,11 @@ function cosmosChain(chain) {
72
72
  throw new Error('Use a Cosmos network such as "cosmos:cosmoshub-4"');
73
73
  }
74
74
  const value = typeof chain === "string" ? { chainId: chain.slice("cosmos:".length) } : chain;
75
+ if (typeof value?.chainId !== "string") {
76
+ throw new Error(
77
+ 'Pass a Cosmos chain as { chainId } or a network such as "cosmos:cosmoshub-4"'
78
+ );
79
+ }
75
80
  const network = `cosmos:${value.chainId}`;
76
81
  if (!cosmosNetworkPattern.test(network)) {
77
82
  throw new Error(
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  identifier
3
- } from "./chunk-IXLY3A7B.js";
3
+ } from "./chunk-BE5V6RFD.js";
4
4
 
5
5
  // src/profiles.ts
6
6
  import { z } from "zod";
@@ -10,8 +10,12 @@ var profileVisibilitySchema = z.enum([
10
10
  "participants",
11
11
  "public"
12
12
  ]);
13
- var profileDefaultsSchema = z.enum(["generated", "accounts"]);
14
13
  var avatarProviderSchema = z.enum(["x", "discord", "google"]);
14
+ var profileDefaultProviderSchema = z.enum(["x", "discord"]);
15
+ var profileDefaultsSchema = z.array(profileDefaultProviderSchema).max(profileDefaultProviderSchema.options.length).refine(
16
+ (providers) => new Set(providers).size === providers.length,
17
+ "List each provider once"
18
+ );
15
19
  var avatarSeedSchema = z.string().min(1).max(100);
16
20
  var profileAvatarSchema = z.discriminatedUnion("source", [
17
21
  z.object({
@@ -71,55 +75,38 @@ var ownProfileSchema = profileSummarySchema.extend({
71
75
  })
72
76
  )
73
77
  });
74
- var publicProfileSchema = profileSummarySchema.extend({
75
- /** The profile is the viewer's own. */
76
- self: z.boolean(),
77
- leaderboards: z.array(
78
- z.object({
79
- leaderboard: identifier,
80
- key: identifier.optional(),
81
- title: z.string(),
82
- rank: count.positive(),
83
- score: z.number().int().safe(),
84
- /** Ranked participants on the board. */
85
- total: count
86
- })
87
- ).nullable(),
88
- quests: z.array(
89
- z.object({
90
- quest: identifier,
91
- key: identifier.optional(),
92
- title: z.string(),
93
- completions: count.positive(),
94
- /** Null for completions recorded before completion times were. */
95
- lastCompletedAt: count.nullable()
96
- })
97
- ).max(200).nullable(),
98
- referrals: z.object({
99
- /** Members this member invited. */
100
- attributed: count,
101
- programs: z.array(
102
- z.object({
103
- program: identifier,
104
- key: identifier.optional(),
105
- title: z.string(),
106
- qualified: count,
107
- milestones: z.array(
108
- z.object({ id: identifier, count, reached: z.boolean() })
109
- )
110
- })
111
- )
112
- }).nullable()
78
+ var cursor = z.string().min(1).max(512);
79
+ var profileCompletionQuerySchema = z.object({
80
+ limit: z.coerce.number().int().min(1).max(100).default(20),
81
+ cursor: cursor.optional()
82
+ }).strict();
83
+ var profileCompletionSchema = z.object({
84
+ quest: identifier,
85
+ key: identifier.optional(),
86
+ title: z.string(),
87
+ completions: count.positive(),
88
+ /** Null for completions recorded before completion times were. */
89
+ lastCompletedAt: count.nullable()
90
+ });
91
+ var profileCompletionPageSchema = z.object({
92
+ items: z.array(profileCompletionSchema),
93
+ nextCursor: cursor.nullable()
94
+ });
95
+ var profileReferralSchema = z.object({
96
+ program: identifier,
97
+ key: identifier.optional(),
98
+ title: z.string(),
99
+ /** Members this member invited. Invitations are shared by every program. */
100
+ invited: count,
101
+ /** Invited members who qualified in this program. */
102
+ qualified: count,
103
+ milestones: z.array(
104
+ z.object({ id: identifier, count, reached: z.boolean() })
105
+ )
113
106
  });
114
107
  var profileSettingsSchema = z.object({
115
108
  visibility: profileVisibilitySchema,
116
109
  defaults: profileDefaultsSchema,
117
- /** The sections a profile page shows. */
118
- sections: z.object({
119
- leaderboards: z.boolean(),
120
- quests: z.boolean(),
121
- referrals: z.boolean()
122
- }),
123
110
  revision: count,
124
111
  actor: z.string().nullable(),
125
112
  updatedAt: count.nullable()
@@ -151,20 +138,26 @@ var managedProfileSchema = ownProfileSchema.omit({ options: true }).extend({
151
138
  var AVATAR_UPLOAD_LIMIT = 5 * 1024 * 1024;
152
139
  var avatarUploadTypes = ["image/jpeg", "image/png", "image/webp"];
153
140
  function isProfileParticipantRoute(path, method) {
154
- return method === "GET" && (path === "/v1/me/profile" || /^\/v1\/profiles\/[\w-]+$/.test(path)) || method === "POST" && (path === "/v1/me/profile" || path === "/v1/me/profile/avatar");
141
+ return method === "GET" && (path === "/v1/me/profile" || /^\/v1\/profiles\/[\w-]+(?:\/completions|\/referrals\/[\w-]+)?$/.test(
142
+ path
143
+ ) || /^\/v1\/leaderboards\/[\w-]+\/profiles\/[\w-]+$/.test(path)) || method === "POST" && (path === "/v1/me/profile" || path === "/v1/me/profile/avatar");
155
144
  }
156
145
 
157
146
  export {
158
147
  profileVisibilitySchema,
159
- profileDefaultsSchema,
160
148
  avatarProviderSchema,
149
+ profileDefaultProviderSchema,
150
+ profileDefaultsSchema,
161
151
  avatarSeedSchema,
162
152
  profileAvatarSchema,
163
153
  profileSummarySchema,
164
154
  displayNameSchema,
165
155
  profileUpdateSchema,
166
156
  ownProfileSchema,
167
- publicProfileSchema,
157
+ profileCompletionQuerySchema,
158
+ profileCompletionSchema,
159
+ profileCompletionPageSchema,
160
+ profileReferralSchema,
168
161
  profileSettingsSchema,
169
162
  profileSettingsInputSchema,
170
163
  profileModerationSchema,
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  createRelayClient
3
- } from "./chunk-D6AIUNSM.js";
3
+ } from "./chunk-5LLU7UUV.js";
4
4
  import {
5
5
  cosmosChain
6
- } from "./chunk-M3R5V5WC.js";
6
+ } from "./chunk-LAKQCIHX.js";
7
7
 
8
8
  // src/base58.ts
9
9
  var alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
@@ -315,6 +315,173 @@ function discoverCosmosWallets(chain) {
315
315
  }
316
316
  return wallets;
317
317
  }
318
+ function cosmosChainList(chains) {
319
+ return chains === void 0 ? [] : Array.isArray(chains) ? [...chains] : [chains];
320
+ }
321
+ async function discoverSignInWallets(families, cosmos) {
322
+ const tagged = (network, wallets) => wallets.map((wallet) => ({ ...wallet, network }));
323
+ const solana = families.includes("solana") ? tagged("solana", discoverSolanaWallets()) : [];
324
+ const chains = families.includes("cosmos") ? tagged(
325
+ "cosmos",
326
+ cosmosChainList(cosmos).flatMap((chain) => discoverCosmosWallets(chain))
327
+ ) : [];
328
+ const evm = families.includes("eip155") ? tagged("eip155", await discoverEvmWallets()) : [];
329
+ return [...evm, ...solana, ...chains];
330
+ }
331
+
332
+ // src/sign-in-options.ts
333
+ var providerLabels = {
334
+ google: "Google",
335
+ apple: "Apple",
336
+ x: "X",
337
+ discord: "Discord"
338
+ };
339
+ var familyLabels = {
340
+ solana: "Solana",
341
+ eip155: "EVM",
342
+ cosmos: "Cosmos"
343
+ };
344
+ function walletLabels(wallets) {
345
+ const named = wallets.map(
346
+ (wallet) => wallets.some((other) => other !== wallet && other.name === wallet.name) ? `${wallet.name} (${wallet.signer.network?.slice("cosmos:".length) ?? familyLabels[wallet.network]})` : wallet.name
347
+ );
348
+ const seen = /* @__PURE__ */ new Map();
349
+ return named.map((label) => {
350
+ if (named.indexOf(label) === named.lastIndexOf(label)) {
351
+ return label;
352
+ }
353
+ const count = (seen.get(label) ?? 0) + 1;
354
+ seen.set(label, count);
355
+ return `${label} ${count}`;
356
+ });
357
+ }
358
+ function cosmosChainsError(chains) {
359
+ try {
360
+ for (const chain of cosmosChainList(chains)) {
361
+ cosmosChain(chain);
362
+ }
363
+ return null;
364
+ } catch (cause) {
365
+ return cause instanceof Error ? cause.message : String(cause);
366
+ }
367
+ }
368
+ function signInOptionsFrom(methods, wallets, input) {
369
+ const { actions } = input;
370
+ const invalid = cosmosChainsError(input.cosmos);
371
+ const chains = !invalid && cosmosChainList(input.cosmos).length > 0;
372
+ const offered = methods.wallets.filter(
373
+ (family) => family !== "cosmos" || chains
374
+ );
375
+ const found = wallets.filter((wallet) => offered.includes(wallet.network));
376
+ const labels = walletLabels(found);
377
+ const options = [
378
+ ...methods.providers.map((provider) => ({
379
+ kind: "oauth",
380
+ id: provider,
381
+ label: providerLabels[provider],
382
+ icon: provider,
383
+ start: () => actions.oauth(provider)
384
+ })),
385
+ ...found.map((wallet, index) => ({
386
+ kind: "wallet",
387
+ id: `wallet:${wallet.network}:${wallet.id}`,
388
+ label: labels[index] ?? wallet.name,
389
+ icon: "wallet",
390
+ ...wallet.icon ? { iconUrl: wallet.icon } : {},
391
+ family: wallet.network,
392
+ signer: wallet.signer,
393
+ start: () => actions.wallet(wallet.signer)
394
+ })),
395
+ ...methods.email ? [
396
+ {
397
+ kind: "email",
398
+ id: "email",
399
+ label: "Email",
400
+ icon: "email",
401
+ sendCode: actions.sendCode,
402
+ verifyCode: actions.verifyCode
403
+ }
404
+ ] : []
405
+ ];
406
+ const unavailable = [];
407
+ if (methods.wallets.includes("cosmos") && invalid) {
408
+ unavailable.push({
409
+ reason: "cosmos-chains-invalid",
410
+ families: ["cosmos"],
411
+ message: `This project takes Cosmos wallets, but this app's Cosmos chains are invalid, so none are offered: ${invalid}.`
412
+ });
413
+ } else if (methods.wallets.includes("cosmos") && !chains) {
414
+ unavailable.push({
415
+ reason: "cosmos-chains-missing",
416
+ families: ["cosmos"],
417
+ message: "This project takes Cosmos wallets, but this app names no Cosmos chains, so none are offered. Pass the chains as the cosmos option."
418
+ });
419
+ }
420
+ if (!input.walletsPending && offered.length > 0 && found.length === 0) {
421
+ const names = new Intl.ListFormat("en", { type: "disjunction" }).format(
422
+ offered.map((family) => familyLabels[family])
423
+ );
424
+ unavailable.push({
425
+ reason: "no-wallet-installed",
426
+ families: offered,
427
+ message: `Wallet sign-in accepts ${names} wallets. Install one in this browser, then reload this page.`
428
+ });
429
+ }
430
+ return {
431
+ options,
432
+ unavailable,
433
+ ...methods.error ? { methodsError: methods.error } : {}
434
+ };
435
+ }
436
+ async function readSignInMethods(relay) {
437
+ try {
438
+ const result = await relay.auth.providers();
439
+ return {
440
+ providers: result.providers.filter((entry) => entry.configured).map((entry) => entry.provider),
441
+ email: result.email,
442
+ wallets: result.wallets
443
+ };
444
+ } catch (cause) {
445
+ return {
446
+ providers: [],
447
+ email: true,
448
+ wallets: [],
449
+ error: cause instanceof Error && cause.message ? cause.message : "Couldn't read the project's sign-in methods."
450
+ };
451
+ }
452
+ }
453
+ async function signInOptions(relay, input = {}) {
454
+ const methods = await readSignInMethods(relay);
455
+ const wallets = await discoverSignInWallets(
456
+ methods.wallets,
457
+ cosmosChainsError(input.cosmos) ? void 0 : input.cosmos
458
+ );
459
+ let challenge = null;
460
+ return signInOptionsFrom(methods, wallets, {
461
+ cosmos: input.cosmos,
462
+ actions: {
463
+ async oauth(provider) {
464
+ const { url } = await relay.auth.start(provider, "sign-in");
465
+ window.location.assign(url);
466
+ },
467
+ async sendCode(email) {
468
+ challenge = null;
469
+ challenge = (await relay.auth.emailStart(email)).challenge;
470
+ },
471
+ async verifyCode(code) {
472
+ if (!challenge) {
473
+ throw new Error("Request a new code first.");
474
+ }
475
+ await relay.auth.emailVerify(challenge, code.trim());
476
+ challenge = null;
477
+ },
478
+ async wallet(signer) {
479
+ await relay.auth.wallet.signIn(signer);
480
+ challenge = null;
481
+ }
482
+ }
483
+ });
484
+ }
318
485
 
319
486
  // src/browser.ts
320
487
  function createBrowserRelayClient(options) {
@@ -377,6 +544,12 @@ export {
377
544
  discoverEvmWallets,
378
545
  discoverSolanaWallets,
379
546
  discoverCosmosWallets,
547
+ cosmosChainList,
548
+ discoverSignInWallets,
549
+ cosmosChainsError,
550
+ signInOptionsFrom,
551
+ readSignInMethods,
552
+ signInOptions,
380
553
  createBrowserRelayClient,
381
554
  browserSubmissionStore
382
555
  };
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  profileSummarySchema
3
- } from "./chunk-D6BX627V.js";
3
+ } from "./chunk-MRKFRCCI.js";
4
4
  import {
5
5
  contentMetricSchema,
6
6
  contentMetricsSchema,
7
7
  identifier,
8
8
  pointsRewardSchema,
9
9
  tierRewardSchema
10
- } from "./chunk-IXLY3A7B.js";
10
+ } from "./chunk-BE5V6RFD.js";
11
11
 
12
12
  // src/engagement.ts
13
13
  import { z } from "zod";
@@ -447,6 +447,16 @@ var leaderboardPageSchema = z4.object({
447
447
  nearby: z4.array(leaderboardRowSchema),
448
448
  nextCursor: z4.string().nullable()
449
449
  });
450
+ var leaderboardPlacementSchema = z4.object({
451
+ leaderboard: identifier,
452
+ key: identifier.optional(),
453
+ title: z4.string(),
454
+ profile: identifier,
455
+ rank: integer.positive().nullable(),
456
+ score: integer.nullable(),
457
+ /** Ranked participants on the board. */
458
+ total: integer.nonnegative()
459
+ });
450
460
  var leaderboardPreviewSchema = z4.object({
451
461
  published: publishedLeaderboardSchema,
452
462
  before: leaderboardPageSchema.nullable(),
@@ -601,6 +611,7 @@ export {
601
611
  leaderboardQuerySchema,
602
612
  leaderboardRowSchema,
603
613
  leaderboardPageSchema,
614
+ leaderboardPlacementSchema,
604
615
  leaderboardPreviewSchema,
605
616
  pointsMutationSchema,
606
617
  pointsEntrySchema,