@domino-sdk/relay 0.26.0 → 0.28.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-MZFUQQDP.js";
12
- import "./chunk-S44XSDW2.js";
14
+ } from "./chunk-NHSA6ATH.js";
15
+ import "./chunk-ZP43MHO3.js";
13
16
  import "./chunk-AKB266O5.js";
14
- import "./chunk-7QICEKC2.js";
17
+ import "./chunk-AL5GXMKI.js";
15
18
  import "./chunk-D6BX627V.js";
16
19
  import "./chunk-IXLY3A7B.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
  };
@@ -62,25 +62,37 @@ var solanaBalanceSchema = z2.object({
62
62
  observedAt: z2.number().int().nonnegative()
63
63
  }).strict();
64
64
  var walletChainSchema = z2.enum(["solana", "eip155", "cosmos"]);
65
- var cosmosNetworks = {
66
- "cosmos:pio-mainnet-1": {
67
- chainId: "pio-mainnet-1",
68
- prefix: "pb",
69
- name: "Provenance"
70
- },
71
- "cosmos:pio-testnet-1": {
72
- chainId: "pio-testnet-1",
73
- prefix: "tp",
74
- name: "Provenance testnet"
65
+ var cosmosNetworkPattern = /^cosmos:[-_a-zA-Z0-9]{1,32}$/;
66
+ var cosmosNetworkSchema = z2.custom(
67
+ (value) => typeof value === "string" && cosmosNetworkPattern.test(value),
68
+ "Use a Cosmos network: cosmos:<chain ID>"
69
+ );
70
+ function cosmosChain(chain) {
71
+ if (typeof chain === "string" && !chain.startsWith("cosmos:")) {
72
+ throw new Error('Use a Cosmos network such as "cosmos:cosmoshub-4"');
75
73
  }
76
- };
77
- var cosmosNetworkSchema = z2.enum([
78
- "cosmos:pio-mainnet-1",
79
- "cosmos:pio-testnet-1"
80
- ]);
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
+ }
80
+ const network = `cosmos:${value.chainId}`;
81
+ if (!cosmosNetworkPattern.test(network)) {
82
+ throw new Error(
83
+ "A Cosmos chain ID has 1 to 32 letters, digits, hyphens or underscores"
84
+ );
85
+ }
86
+ if (value.chainInfo && value.chainInfo.chainId !== value.chainId) {
87
+ throw new Error("The chain info describes another chain ID");
88
+ }
89
+ return { ...value, network };
90
+ }
81
91
  var solanaMainnet = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp";
82
92
  var evmAddressSchema = z2.string().regex(/^0x[0-9a-fA-F]{40}$/);
83
- var cosmosAddressSchema = z2.string().min(8).max(90).regex(/^[a-z]{1,20}1[02-9ac-hj-np-z]{38,}$/);
93
+ var cosmosAddressSchema = z2.string().min(8).max(90).regex(
94
+ /^(?:[a-z][a-z0-9]{0,82}1[02-9ac-hj-np-z]{38,}|[A-Z][A-Z0-9]{0,82}1[02-9AC-HJ-NP-Z]{38,})$/
95
+ );
84
96
  var walletAddressInputSchema = z2.discriminatedUnion("chain", [
85
97
  z2.object({ chain: z2.literal("solana"), address: solanaAddressSchema }).strict(),
86
98
  z2.object({
@@ -135,25 +147,20 @@ async function walletAddressInput(signer) {
135
147
  };
136
148
  case "cosmos":
137
149
  if (!signer.network) {
138
- throw new Error("Choose a Cosmos network for this wallet");
150
+ throw new Error("Choose the Cosmos chain for this wallet");
139
151
  }
140
152
  return { chain: "cosmos", network: signer.network, address };
141
153
  }
142
154
  }
143
155
  var WALLETS_PER_CHAIN = 5;
144
- var walletSignInNetworkSchema = z2.enum([
145
- "solana",
146
- "eip155",
147
- "cosmos:pio-mainnet-1",
148
- "cosmos:pio-testnet-1"
149
- ]);
156
+ var walletSignInFamilies = ["solana", "eip155", "cosmos"];
157
+ var walletSignInNetworkSchema = z2.union([z2.enum(walletSignInFamilies), z2.string().regex(cosmosNetworkPattern)]).transform(
158
+ (value) => value.startsWith("cosmos:") ? "cosmos" : value
159
+ );
160
+ var walletSignInNetworksSchema = z2.array(walletSignInNetworkSchema).transform(
161
+ (values) => walletSignInFamilies.filter((family) => values.includes(family))
162
+ );
150
163
  function walletSignInNetwork(wallet) {
151
- if (wallet.chain === "cosmos") {
152
- if (!wallet.network) {
153
- throw new Error("A Cosmos wallet belongs to its own network");
154
- }
155
- return wallet.network;
156
- }
157
164
  return wallet.chain;
158
165
  }
159
166
  function caip10(wallet, network) {
@@ -208,8 +215,8 @@ export {
208
215
  walletProofSchema,
209
216
  solanaBalanceSchema,
210
217
  walletChainSchema,
211
- cosmosNetworks,
212
218
  cosmosNetworkSchema,
219
+ cosmosChain,
213
220
  solanaMainnet,
214
221
  evmAddressSchema,
215
222
  cosmosAddressSchema,
@@ -220,7 +227,9 @@ export {
220
227
  walletUnlinkInputSchema,
221
228
  walletAddressInput,
222
229
  WALLETS_PER_CHAIN,
230
+ walletSignInFamilies,
223
231
  walletSignInNetworkSchema,
232
+ walletSignInNetworksSchema,
224
233
  walletSignInNetwork,
225
234
  caip10,
226
235
  isWalletParticipantRoute,
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  createRelayClient
3
- } from "./chunk-S44XSDW2.js";
3
+ } from "./chunk-ZP43MHO3.js";
4
4
  import {
5
- cosmosNetworks
6
- } from "./chunk-7QICEKC2.js";
5
+ cosmosChain
6
+ } from "./chunk-AL5GXMKI.js";
7
7
 
8
8
  // src/base58.ts
9
9
  var alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
@@ -141,14 +141,40 @@ function walletStandardSolanaSigner(wallet) {
141
141
  }
142
142
  };
143
143
  }
144
- function cosmosSigner(provider, network, info = {}) {
145
- const { chainId } = cosmosNetworks[network];
144
+ var unknownChain = /no chain info|unknown chain|chain.{0,40}not (?:supported|found)/i;
145
+ function cosmosSigner(provider, chain, info = {}) {
146
+ const { chainId, chainInfo, network } = cosmosChain(chain);
147
+ const wallet = info.name ?? "This wallet";
148
+ async function enable() {
149
+ try {
150
+ await provider.enable(chainId);
151
+ } catch (error) {
152
+ const message = error instanceof Error ? error.message : typeof error === "string" ? error : "";
153
+ if (!unknownChain.test(message)) {
154
+ throw error;
155
+ }
156
+ if (!chainInfo) {
157
+ throw new Error(
158
+ `${wallet} doesn't know the Cosmos chain ${chainId}. Add the chain to the wallet, or pass its chainInfo so the wallet can suggest it.`,
159
+ { cause: error }
160
+ );
161
+ }
162
+ if (!provider.experimentalSuggestChain) {
163
+ throw new Error(
164
+ `${wallet} doesn't know the Cosmos chain ${chainId} and cannot add chains. Add the chain to the wallet, or use a wallet that supports experimentalSuggestChain.`,
165
+ { cause: error }
166
+ );
167
+ }
168
+ await provider.experimentalSuggestChain(chainInfo);
169
+ await provider.enable(chainId);
170
+ }
171
+ }
146
172
  return {
147
173
  chain: "cosmos",
148
174
  network,
149
175
  name: info.name,
150
176
  async address() {
151
- await provider.enable(chainId);
177
+ await enable();
152
178
  return (await provider.getKey(chainId)).bech32Address;
153
179
  },
154
180
  async sign(message, address) {
@@ -267,7 +293,8 @@ function discoverSolanaWallets() {
267
293
  }
268
294
  return wallets;
269
295
  }
270
- function discoverCosmosWallets(network) {
296
+ function discoverCosmosWallets(chain) {
297
+ const { chainId } = cosmosChain(chain);
271
298
  const target = injected();
272
299
  if (!target) {
273
300
  return [];
@@ -280,14 +307,181 @@ function discoverCosmosWallets(network) {
280
307
  ]) {
281
308
  if (typeof provider?.signArbitrary === "function") {
282
309
  wallets.push({
283
- id: `${slug(name)}:${cosmosNetworks[network].chainId}`,
310
+ id: `${slug(name)}:${chainId}`,
284
311
  name,
285
- signer: cosmosSigner(provider, network, { name })
312
+ signer: cosmosSigner(provider, chain, { name })
286
313
  });
287
314
  }
288
315
  }
289
316
  return wallets;
290
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
+ }
291
485
 
292
486
  // src/browser.ts
293
487
  function createBrowserRelayClient(options) {
@@ -350,6 +544,12 @@ export {
350
544
  discoverEvmWallets,
351
545
  discoverSolanaWallets,
352
546
  discoverCosmosWallets,
547
+ cosmosChainList,
548
+ discoverSignInWallets,
549
+ cosmosChainsError,
550
+ signInOptionsFrom,
551
+ readSignInMethods,
552
+ signInOptions,
353
553
  createBrowserRelayClient,
354
554
  browserSubmissionStore
355
555
  };
@@ -32,10 +32,10 @@ import {
32
32
  walletConnectionSchema,
33
33
  walletMessageChallengeSchema,
34
34
  walletProofSchema,
35
- walletSignInNetworkSchema,
35
+ walletSignInNetworksSchema,
36
36
  walletSignatureSchema,
37
37
  walletUnlinkInputSchema
38
- } from "./chunk-7QICEKC2.js";
38
+ } from "./chunk-AL5GXMKI.js";
39
39
  import {
40
40
  AVATAR_UPLOAD_LIMIT,
41
41
  avatarUploadTypes,
@@ -2061,7 +2061,7 @@ function createRelayClient(options) {
2061
2061
  ),
2062
2062
  email: z11.boolean(),
2063
2063
  /** The wallet sign-in this project enabled; older servers omit it. */
2064
- wallets: z11.array(walletSignInNetworkSchema).default([]),
2064
+ wallets: walletSignInNetworksSchema.default([]),
2065
2065
  demo: z11.boolean()
2066
2066
  })
2067
2067
  ),
@@ -2103,7 +2103,7 @@ function createRelayClient(options) {
2103
2103
  ),
2104
2104
  /**
2105
2105
  * Asks the signer for its address, signs the challenge and starts the session. Throws a
2106
- * `RelayError` with status 403 when the project has not enabled this wallet's network.
2106
+ * `RelayError` with status 403 when the project has not enabled this wallet family.
2107
2107
  */
2108
2108
  signIn: async (signer) => {
2109
2109
  const challenge = await request(