@tempoxyz/id 0.0.0-pr-723.sha-e431f51 → 0.0.0-pr-721.sha-70e07db

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.
@@ -4,8 +4,8 @@ import {
4
4
  name,
5
5
  parseName,
6
6
  pending
7
- } from "./chunk-MLNEONHA.js";
8
- import "./chunk-HIKQ4IBM.js";
7
+ } from "./chunk-HAAICPJO.js";
8
+ import "./chunk-RS7QDWBO.js";
9
9
  import "./chunk-YW5DUQT3.js";
10
10
  import "./chunk-MLKGABMK.js";
11
11
  export {
@@ -4,7 +4,7 @@ import {
4
4
  machines,
5
5
  prompt,
6
6
  waiting
7
- } from "./chunk-HIKQ4IBM.js";
7
+ } from "./chunk-RS7QDWBO.js";
8
8
  import "./chunk-MLKGABMK.js";
9
9
  export {
10
10
  create,
@@ -2,7 +2,7 @@ import {
2
2
  AccessKey_exports,
3
3
  Accounts_exports,
4
4
  Actions_exports
5
- } from "./chunk-HIKQ4IBM.js";
5
+ } from "./chunk-RS7QDWBO.js";
6
6
 
7
7
  // src/Session.ts
8
8
  import * as Fs from "node:fs/promises";
@@ -5,7 +5,7 @@ import {
5
5
  expired,
6
6
  from,
7
7
  revokeAccessKey
8
- } from "./chunk-HIKQ4IBM.js";
8
+ } from "./chunk-RS7QDWBO.js";
9
9
  import {
10
10
  from as from2
11
11
  } from "./chunk-YW5DUQT3.js";
@@ -18,6 +18,7 @@ import {
18
18
  // ../../accounts/src/Accounts.ts
19
19
  var Accounts_exports = {};
20
20
  __export(Accounts_exports, {
21
+ ChainInvalidError: () => ChainInvalidError,
21
22
  ChainUnavailableError: () => ChainUnavailableError,
22
23
  ChallengeWithoutKeyError: () => ChallengeWithoutKeyError,
23
24
  ClientIdRequiredError: () => ClientIdRequiredError,
@@ -29,7 +30,7 @@ __export(Accounts_exports, {
29
30
  RevokedError: () => RevokedError,
30
31
  SignedOutError: () => SignedOutError2,
31
32
  SupersededError: () => SupersededError,
32
- create: () => create4,
33
+ create: () => create5,
33
34
  from: () => from6
34
35
  });
35
36
 
@@ -1005,9 +1006,9 @@ async function authorizeUrl(auth, options) {
1005
1006
  if (!accessKey2 && options.challenge !== void 0)
1006
1007
  throw new ChallengeWithoutKeyError();
1007
1008
  const redirectUri = options.redirectUri ?? auth.redirectUri ?? `${window.location.origin}/`;
1008
- const key = accessKey2 && !("address" in accessKey2) ? await resolve(accessKey2) : void 0;
1009
+ const key = accessKey2 ? await resolve(accessKey2) : void 0;
1009
1010
  const pending = from2({
1010
- ...key ? key.material : accessKey2 ? {} : { key: false },
1011
+ ...key ? key.material : { key: false },
1011
1012
  chainId: auth.chainId,
1012
1013
  clientId: auth.clientId,
1013
1014
  redirectUri,
@@ -1015,13 +1016,9 @@ async function authorizeUrl(auth, options) {
1015
1016
  state: Base644.fromBytes(Bytes2.random(16), base64url),
1016
1017
  verifier: Base644.fromBytes(Bytes2.random(32), base64url)
1017
1018
  });
1018
- const authorization2 = (() => {
1019
- if (!accessKey2) return void 0;
1020
- if ("address" in accessKey2) return keyAuthorization(auth, { accessKey: accessKey2 });
1021
- return keyAuthorization(auth, {
1022
- accessKey: { ...accessKey2, account: key.accessKey }
1023
- });
1024
- })();
1019
+ const authorization2 = key && accessKey2 ? keyAuthorization(auth, {
1020
+ accessKey: { ...accessKey2, account: key.accessKey }
1021
+ }) : void 0;
1025
1022
  const url = new URL("/oauth2/authorize", auth.url);
1026
1023
  const parameters = new URLSearchParams({
1027
1024
  ...options.challenge === void 0 ? {} : { challenge: options.challenge },
@@ -1078,39 +1075,23 @@ function request(auth, options) {
1078
1075
  };
1079
1076
  }
1080
1077
  function keyAuthorization(auth, options) {
1081
- const { accessKey: accessKey2 } = options;
1082
- const permissions2 = resolve2(accessKey2, {
1078
+ const { account: signer } = options.accessKey;
1079
+ const permissions2 = resolve2(options.accessKey, {
1083
1080
  chainId: auth.chainId
1084
1081
  });
1085
- const named = (() => {
1086
- if ("address" in accessKey2)
1087
- return {
1088
- account: options.account ?? accessKey2.access,
1089
- address: accessKey2.address,
1090
- keyType: accessKey2.type ?? "secp256k1",
1091
- witness: accessKey2.witness
1092
- };
1093
- const { account: signer } = accessKey2;
1094
- return {
1095
- account: options.account ?? (signer.accessKeyAddress ? signer.address : void 0),
1096
- address: signer.accessKeyAddress ?? signer.address,
1097
- keyType: signer.keyType,
1098
- witness: void 0
1099
- };
1100
- })();
1082
+ const account2 = options.account ?? (signer.accessKeyAddress ? signer.address : void 0);
1101
1083
  return {
1102
- ...named.account ? { account: named.account } : {},
1103
- address: named.address,
1084
+ ...account2 ? { account: account2 } : {},
1085
+ address: signer.accessKeyAddress ?? signer.address,
1104
1086
  chainId: Hex2.fromNumber(permissions2.chainId),
1105
1087
  expiry: permissions2.expiry,
1106
- keyType: named.keyType,
1088
+ keyType: signer.keyType,
1107
1089
  limits: permissions2.limits?.map(({ limit, period, token: token2 }) => ({
1108
1090
  limit: Hex2.fromNumber(limit),
1109
1091
  ...period ? { period } : {},
1110
1092
  token: token2
1111
1093
  })),
1112
- scopes: permissions2.scopes,
1113
- ...named.witness ? { witness: named.witness } : {}
1094
+ scopes: permissions2.scopes
1114
1095
  };
1115
1096
  }
1116
1097
  function funding(options) {
@@ -1788,7 +1769,7 @@ async function open(auth, options) {
1788
1769
  throw new OriginError({ origin: window.location.origin, redirectUri });
1789
1770
  if (mode === "popup" && options.mode !== "popup" && !activated()) {
1790
1771
  const address2 = await abortable(read2(), { signal });
1791
- const Sheet = await import("./Sheet-2NWDVPFR.js");
1772
+ const Sheet = await import("./Sheet-KNMK2T55.js");
1792
1773
  return await new Promise((resolve3, reject) => {
1793
1774
  const abort = () => {
1794
1775
  close();
@@ -1839,7 +1820,7 @@ async function watch(auth, options) {
1839
1820
  try {
1840
1821
  return await new Promise(
1841
1822
  (resolve3, reject) => {
1842
- void import("./Sheet-2NWDVPFR.js").then(
1823
+ void import("./Sheet-KNMK2T55.js").then(
1843
1824
  (Sheet) => {
1844
1825
  if (settled) return;
1845
1826
  unblock = Sheet.waiting({
@@ -1904,7 +1885,7 @@ function parse(url, options) {
1904
1885
  async function frame(auth, options) {
1905
1886
  const { redirectUri, signal, toUrl } = options;
1906
1887
  const address2 = await abortable(options.address, { signal });
1907
- const Sheet = await import("./Sheet-2NWDVPFR.js");
1888
+ const Sheet = await import("./Sheet-KNMK2T55.js");
1908
1889
  signal?.throwIfAborted();
1909
1890
  let close;
1910
1891
  let abort;
@@ -1970,22 +1951,22 @@ function save(auth, pending) {
1970
1951
  } catch {
1971
1952
  }
1972
1953
  }
1973
- function take(auth) {
1974
- const storage = session(auth);
1954
+ function take(scope) {
1955
+ const storage = session(scope);
1975
1956
  if (!storage) return void 0;
1976
1957
  try {
1977
1958
  const value = storage.getItem(storageKey);
1978
1959
  if (!value) return void 0;
1979
1960
  const ticket2 = JSON.parse(value);
1980
- if (!owns(auth, ticket2)) return void 0;
1961
+ if (!owns(scope, ticket2)) return void 0;
1981
1962
  storage.removeItem(storageKey);
1982
1963
  return ticket2;
1983
1964
  } catch {
1984
1965
  return void 0;
1985
1966
  }
1986
1967
  }
1987
- function owns(auth, pending) {
1988
- return (pending.clientId ?? auth.clientId) === auth.clientId && (pending.chainId ?? auth.chainId) === auth.chainId;
1968
+ function owns(scope, pending) {
1969
+ return (pending.clientId ?? scope.clientId) === scope.clientId && (scope.chainId === void 0 || (pending.chainId ?? scope.chainId) === scope.chainId);
1989
1970
  }
1990
1971
  function ticket(pending) {
1991
1972
  return {
@@ -1997,8 +1978,8 @@ function ticket(pending) {
1997
1978
  verifier: pending.verifier
1998
1979
  };
1999
1980
  }
2000
- function session(auth) {
2001
- if (auth.store) return void 0;
1981
+ function session(scope) {
1982
+ if (scope.store) return void 0;
2002
1983
  try {
2003
1984
  return typeof sessionStorage === "undefined" ? void 0 : sessionStorage;
2004
1985
  } catch {
@@ -2009,7 +1990,9 @@ var storageKey = "tempo-id:redirect";
2009
1990
 
2010
1991
  // ../../accounts/src/actions/redirect.ts
2011
1992
  function complete3(auth, options = {}) {
2012
- const owner = `${auth.clientId}:${auth.chainId}`;
1993
+ const chainId = options.anyChain ? void 0 : auth.chainId;
1994
+ const scope = { chainId, clientId: auth.clientId, store: auth.store };
1995
+ const owner = `${auth.clientId}:${chainId ?? "*"}`;
2013
1996
  const store2 = get2(auth.store);
2014
1997
  let results = completed.get(store2);
2015
1998
  if (!results) completed.set(store2, results = /* @__PURE__ */ new Map());
@@ -2017,7 +2000,7 @@ function complete3(auth, options = {}) {
2017
2000
  if (pending) return pending;
2018
2001
  const result = (async () => {
2019
2002
  const url = new URL(window.location.href);
2020
- const ticket2 = take(auth);
2003
+ const ticket2 = take(scope);
2021
2004
  const early = ticket2 && url.searchParams.has("code") && url.searchParams.get("state") === ticket2.state ? redeem(auth, { pending: ticket2, url }) : void 0;
2022
2005
  early?.catch(() => void 0);
2023
2006
  const state = url.searchParams.getAll("state").at(-1);
@@ -2033,7 +2016,7 @@ function complete3(auth, options = {}) {
2033
2016
  const stored = entry?.value;
2034
2017
  const redirectUri = stored?.redirectUri ?? url.origin;
2035
2018
  const registered = new URL(redirectUri).searchParams;
2036
- if (stored != null && !owns(auth, stored)) return void 0;
2019
+ if (stored != null && !owns(scope, stored)) return void 0;
2037
2020
  const ours = stored != null && state === stored.state;
2038
2021
  const removed = ours && entry ? (async () => store2.removeItem(entry.key))() : void 0;
2039
2022
  removed?.catch(() => void 0);
@@ -2072,7 +2055,7 @@ function complete3(auth, options = {}) {
2072
2055
  removed
2073
2056
  ]);
2074
2057
  return finish({
2075
- accessKey: options.accessKey,
2058
+ accessKey: own(options.accessKey),
2076
2059
  body,
2077
2060
  pending: stored
2078
2061
  });
@@ -2085,7 +2068,7 @@ async function createUrl(auth, options = {}) {
2085
2068
  }
2086
2069
  async function handleCallback(auth, options) {
2087
2070
  return finish({
2088
- accessKey: options.accessKey,
2071
+ accessKey: own(options.accessKey),
2089
2072
  body: await redeem(auth, {
2090
2073
  pending: options.pending,
2091
2074
  url: new URL(options.url)
@@ -2114,7 +2097,7 @@ function handleResult(options) {
2114
2097
  status: 400
2115
2098
  });
2116
2099
  return finish({
2117
- accessKey: options.accessKey,
2100
+ accessKey: own(options.accessKey),
2118
2101
  body: authorization2,
2119
2102
  pending: options.pending
2120
2103
  });
@@ -2192,24 +2175,13 @@ function finish(options) {
2192
2175
  signedIn: true,
2193
2176
  status: 400
2194
2177
  });
2195
- if (options.accessKey && "address" in options.accessKey) {
2196
- const tokens3 = tokens(body);
2197
- return {
2198
- ...tokens3,
2199
- key: from({
2200
- account: body.account,
2201
- keyAuthorization: body.key_authorization
2202
- }),
2203
- user: user(tokens3)
2204
- };
2205
- }
2206
2178
  return authorization(
2207
2179
  {
2208
2180
  account: body.account,
2209
2181
  key_authorization: body.key_authorization,
2210
2182
  tokens: body
2211
2183
  },
2212
- { accessKey: own(options.accessKey), material }
2184
+ { accessKey: options.accessKey, material }
2213
2185
  );
2214
2186
  }
2215
2187
  async function prefetch(auth) {
@@ -2530,11 +2502,11 @@ async function authorize3(auth, options) {
2530
2502
  broadcast?.close();
2531
2503
  unwatch?.();
2532
2504
  subscription.unsubscribe();
2533
- const { keep, owned } = machines.ending(actor.getSnapshot(), {
2505
+ const { keep: keep2, owned } = machines.ending(actor.getSnapshot(), {
2534
2506
  call,
2535
2507
  framed: sheet !== void 0
2536
2508
  });
2537
- const kept = keep && sheet !== void 0 && sheet.hide();
2509
+ const kept = keep2 && sheet !== void 0 && sheet.hide();
2538
2510
  actor.send({
2539
2511
  call,
2540
2512
  kept: kept && sheet ? { options: { redirectUri }, redirectUri, sheet } : void 0,
@@ -2731,7 +2703,9 @@ function from4(value) {
2731
2703
  return value;
2732
2704
  }
2733
2705
  function expired2(session2) {
2734
- if (session2.key) return expired(session2.key);
2706
+ if (session2.key)
2707
+ return expired(session2.key) && !session2.keys?.some((entry) => !expired(entry));
2708
+ if (session2.keys?.some((entry) => !expired(entry))) return false;
2735
2709
  return !session2.refreshToken && session2.expiresAt <= Date.now();
2736
2710
  }
2737
2711
 
@@ -3314,11 +3288,11 @@ function thirdParty(clientId) {
3314
3288
  }
3315
3289
 
3316
3290
  // ../../accounts/src/internal/Core.ts
3317
- import { Address as Address4 } from "ox";
3291
+ import { Address as Address5 } from "ox";
3318
3292
  import { KeyAuthorization as KeyAuthorization3 } from "ox/tempo";
3319
3293
 
3320
3294
  // ../../accounts/src/internal/Session.ts
3321
- import { Bytes as Bytes3, Hash as Hash3 } from "ox";
3295
+ import { Address as Address4, Bytes as Bytes3, Hash as Hash3 } from "ox";
3322
3296
  import {
3323
3297
  assertEvent,
3324
3298
  assign as assign2,
@@ -3327,7 +3301,7 @@ import {
3327
3301
  waitFor
3328
3302
  } from "xstate";
3329
3303
  function create3(options) {
3330
- const { enabled, name, onSignIn, onSignOut, signOut: signOut2, store: store2 } = options;
3304
+ const { chainId, enabled, name, onSignIn, onSignOut, signOut: signOut2, store: store2 } = options;
3331
3305
  const writes = store2 ? queue(store2, { getFn: options.getFn }) : void 0;
3332
3306
  const channel2 = enabled && writes && typeof document !== "undefined" && typeof BroadcastChannel !== "undefined" ? new BroadcastChannel(`${name}:session`) : void 0;
3333
3307
  if (channel2)
@@ -3830,7 +3804,8 @@ function create3(options) {
3830
3804
  const signIn5 = !!session2 && !options2.update && !options2.restore;
3831
3805
  const replaced = signIn5 ? context().session : void 0;
3832
3806
  const since = obtained;
3833
- set(session2, { signIn: signIn5 });
3807
+ const kept = session2 ? keep(context().session, session2, { chainId: chainId() }) : session2;
3808
+ set(kept, { signIn: signIn5 });
3834
3809
  const clears = !!session2 && !options2.update && machines2.clears({ current: context(), started });
3835
3810
  if (clears) actor.send({ type: "change.commit" });
3836
3811
  const rotation = options2.sent && session2?.refreshToken && history ? (async () => rotations.write(await history, {
@@ -3845,7 +3820,7 @@ function create3(options) {
3845
3820
  ]);
3846
3821
  if (replaced?.refreshToken && replaced.refreshToken !== session2?.refreshToken)
3847
3822
  void revokeReplaced(replaced, since);
3848
- if (session2) await onSignIn?.(session2);
3823
+ if (kept) await onSignIn?.(kept);
3849
3824
  },
3850
3825
  fail: async (error3, failure = {}) => {
3851
3826
  if (overtaken()) throw await superseded(void 0, error3, failure);
@@ -4051,6 +4026,36 @@ var signedOut_status = {
4051
4026
  session: void 0,
4052
4027
  status: "signedOut"
4053
4028
  };
4029
+ function keep(replaced, session2, options) {
4030
+ if (!replaced || replaced.user.id !== session2.user.id) return session2;
4031
+ const address2 = session2.key?.account ?? session2.account?.address ?? session2.keys?.[0]?.account;
4032
+ if (!address2) return session2;
4033
+ const taken = /* @__PURE__ */ new Set([
4034
+ session2.key?.chainId ?? options.chainId,
4035
+ ...(session2.keys ?? []).map((entry) => entry.chainId)
4036
+ ]);
4037
+ const kept = [replaced.key, ...replaced.keys ?? []].filter(
4038
+ (entry) => !!entry && !taken.has(entry.chainId) && !expired(entry) && Address4.isEqual(entry.account, address2)
4039
+ );
4040
+ if (kept.length === 0) return session2;
4041
+ return { ...session2, keys: [...session2.keys ?? [], ...kept] };
4042
+ }
4043
+ function toChain(session2, options) {
4044
+ const { chainId } = options;
4045
+ if (session2.key?.chainId === chainId) return session2;
4046
+ if (!session2.key && !session2.keys?.length && !session2.account) return session2;
4047
+ const live = [session2.key, ...session2.keys ?? []].filter(
4048
+ (entry) => !!entry && !expired(entry)
4049
+ );
4050
+ const key = live.find((entry) => entry.chainId === chainId);
4051
+ const keys = live.filter((entry) => entry !== key);
4052
+ const { account: _account, key: _key, keys: _keys, ...rest } = session2;
4053
+ return {
4054
+ ...rest,
4055
+ ...key ? { key } : {},
4056
+ ...keys.length ? { keys } : {}
4057
+ };
4058
+ }
4054
4059
  function toSaved(session2) {
4055
4060
  if (!session2) return void 0;
4056
4061
  const { account: account2, ...rest } = session2;
@@ -4483,7 +4488,7 @@ async function run(context, parameters) {
4483
4488
  const held = await context.session.load();
4484
4489
  const change = context.session.change({ restore: true });
4485
4490
  const renewing = context.session.renewing()?.key;
4486
- const derived = parameters.renew && parameters.accessKey === void 0 && renewing?.lifetime && (parameters.account === void 0 || Address4.isEqual(parameters.account, renewing.account)) ? {
4491
+ const derived = parameters.renew && parameters.accessKey === void 0 && renewing?.lifetime && (parameters.account === void 0 || Address5.isEqual(parameters.account, renewing.account)) ? {
4487
4492
  ...permissions(renewing),
4488
4493
  expiry: Math.floor(Date.now() / 1e3) + renewing.lifetime
4489
4494
  } : void 0;
@@ -4699,19 +4704,62 @@ var interactive = /* @__PURE__ */ new Set([
4699
4704
  "upgrade_required",
4700
4705
  "webauthn_required"
4701
4706
  ]);
4707
+ async function switchChain(context, options) {
4708
+ const { chainId, select } = options;
4709
+ if (!Number.isSafeInteger(chainId) || chainId <= 0)
4710
+ throw new ChainInvalidError({ chainId });
4711
+ if (!options.latest()) return;
4712
+ await context.session.load();
4713
+ const held = context.session.get();
4714
+ const account2 = held && !toChain(held, { chainId }).key ? await options.account(chainId).catch((error3) => {
4715
+ if (options.latest()) throw error3;
4716
+ return void 0;
4717
+ }) : void 0;
4718
+ if (!options.latest()) return;
4719
+ await select(chainId);
4720
+ if (!held) return;
4721
+ await context.session.exclusive(async () => {
4722
+ const latest = await context.session.reload();
4723
+ if (!latest) return;
4724
+ if (context.chain.get() !== chainId) return;
4725
+ if (signedInSince(latest, { chainId, held })) return;
4726
+ const moved = toChain(latest, { chainId });
4727
+ if (moved === latest && !account2) return;
4728
+ await context.session.change({ update: true }).commit(account2 ? { ...moved, account: account2 } : moved);
4729
+ });
4730
+ }
4731
+ function signedInSince(current, options) {
4732
+ const { chainId, held } = options;
4733
+ if (current.user.id !== held.user.id) return true;
4734
+ const ids2 = new Set(
4735
+ [held.key, ...held.keys ?? []].map(
4736
+ (entry) => entry?.keyAuthorization.keyId.toLowerCase()
4737
+ )
4738
+ );
4739
+ if ([current.key, ...current.keys ?? []].some(
4740
+ (entry) => entry && Number(entry.chainId) === chainId && !ids2.has(entry.keyAuthorization.keyId.toLowerCase())
4741
+ ))
4742
+ return true;
4743
+ return !!current.account && !!held.account && !Address5.isEqual(current.account.address, held.account.address);
4744
+ }
4702
4745
  async function upgradeAccount(context, parameters = {}) {
4703
4746
  const current = await context.session.load();
4704
- const key = current?.key;
4747
+ const chainId = context.chain.get();
4748
+ const key = [current?.key, ...current?.keys ?? []].find(
4749
+ (entry) => entry && Number(entry.chainId) === chainId
4750
+ );
4705
4751
  const upgraded = await account_exports.upgrade(context.config, {
4706
4752
  // The session's own access key signs its registration, also one with material that the store kept.
4707
4753
  ...key && (key.keyPair || key.privateKey) ? { accessKey: toAccount(from(key)) } : {},
4708
4754
  addOwner: parameters.addOwner,
4755
+ chainId,
4709
4756
  getFn: parameters.getFn ?? context.config.getFn,
4710
4757
  key
4711
4758
  });
4712
4759
  if (current)
4713
4760
  await context.session.exclusive(async () => {
4714
4761
  const latest = await context.session.reload();
4762
+ if (context.chain.get() !== chainId) return;
4715
4763
  if (latest?.user.id !== current.user.id) return;
4716
4764
  const change = context.session.change({ update: true });
4717
4765
  await change.commit({ ...latest, account: upgraded });
@@ -4743,7 +4791,7 @@ var signInIds = /* @__PURE__ */ new Set([
4743
4791
  function plugin() {
4744
4792
  let loading;
4745
4793
  function load() {
4746
- loading ??= import("./dialog-PR35OGJM.js").then((module) => module.dialog()).catch((error3) => {
4794
+ loading ??= import("./dialog-Z3BKD2TS.js").then((module) => module.dialog()).catch((error3) => {
4747
4795
  loading = void 0;
4748
4796
  throw error3;
4749
4797
  });
@@ -4778,6 +4826,60 @@ function plugin() {
4778
4826
  });
4779
4827
  }
4780
4828
 
4829
+ // ../../accounts/src/internal/InstanceChain.ts
4830
+ function create4(options) {
4831
+ const { name, store: store2 } = options;
4832
+ const key = `${name}:chain`;
4833
+ let chainId = options.chainId;
4834
+ const listeners = /* @__PURE__ */ new Set();
4835
+ let loading;
4836
+ let writing = Promise.resolve();
4837
+ function apply(next) {
4838
+ if (next === chainId) return;
4839
+ const previous = chainId;
4840
+ chainId = next;
4841
+ for (const listener of listeners) listener(next, previous);
4842
+ }
4843
+ function load() {
4844
+ if (!store2 || loading === "read") return Promise.resolve();
4845
+ loading ??= (async () => {
4846
+ await writing.catch(() => void 0);
4847
+ if (loading === "read") return;
4848
+ const stored = await store2.getItem(key);
4849
+ if (valid(stored)) apply(stored);
4850
+ loading = "read";
4851
+ })().catch((error3) => {
4852
+ loading = void 0;
4853
+ throw error3;
4854
+ });
4855
+ return loading;
4856
+ }
4857
+ return {
4858
+ configured: options.chainId,
4859
+ get: () => chainId,
4860
+ load,
4861
+ loaded: () => !store2 || loading === "read",
4862
+ async set(next) {
4863
+ await load().catch(() => void 0);
4864
+ if (!store2) return apply(next);
4865
+ const write = writing.catch(() => void 0).then(async () => {
4866
+ await store2.setItem(key, next);
4867
+ apply(next);
4868
+ loading = "read";
4869
+ });
4870
+ writing = write;
4871
+ await write;
4872
+ },
4873
+ subscribe(listener) {
4874
+ listeners.add(listener);
4875
+ return () => listeners.delete(listener);
4876
+ }
4877
+ };
4878
+ }
4879
+ function valid(value) {
4880
+ return typeof value === "number" && Number.isSafeInteger(value) && value > 0;
4881
+ }
4882
+
4781
4883
  // ../../accounts/src/plugins/funding.ts
4782
4884
  var SignedOutError = class extends Error {
4783
4885
  name = "Plugins.funding.SignedOutError";
@@ -4848,6 +4950,14 @@ async function accessToken(context, options) {
4848
4950
  }
4849
4951
 
4850
4952
  // ../../accounts/src/Accounts.ts
4953
+ var ChainInvalidError = class extends Error {
4954
+ name = "Accounts.ChainInvalidError";
4955
+ constructor(options) {
4956
+ super(
4957
+ `Invalid chain ID: ${String(options.chainId)} is not a positive integer. Pass the ID of a chain, such as \`tempo.id\`.`
4958
+ );
4959
+ }
4960
+ };
4851
4961
  var ChainUnavailableError = class extends Error {
4852
4962
  name = "Accounts.ChainUnavailableError";
4853
4963
  constructor(options) {
@@ -4970,7 +5080,7 @@ function from6(options = {}) {
4970
5080
  url: url ?? defaultUrl
4971
5081
  };
4972
5082
  }
4973
- function create4(options = {}) {
5083
+ function create5(options = {}) {
4974
5084
  const {
4975
5085
  accessKey: accessKey_option,
4976
5086
  connections: connectionsOptions,
@@ -5011,8 +5121,18 @@ function create4(options = {}) {
5011
5121
  }
5012
5122
  const name = `tempo-id:session:${JSON.stringify([new URL(config.url).origin, config.clientId, config.chainId])}`;
5013
5123
  const store2 = get2(config.store);
5124
+ const chain = create4({
5125
+ chainId: config.chainId,
5126
+ name,
5127
+ store: enabled ? store2 : void 0
5128
+ });
5129
+ const switches = { count: 0, last: Promise.resolve() };
5130
+ Object.defineProperty(config, "chainId", { enumerable: true, get: chain.get });
5131
+ if (enabled && typeof document !== "undefined")
5132
+ chain.load().catch(() => void 0);
5014
5133
  const unanswered2 = /* @__PURE__ */ new WeakSet();
5015
5134
  const session2 = create3({
5135
+ chainId: chain.get,
5016
5136
  enabled,
5017
5137
  getFn: config.getFn,
5018
5138
  name,
@@ -5085,13 +5205,28 @@ function create4(options = {}) {
5085
5205
  });
5086
5206
  const context = {
5087
5207
  accessKey: accessKey2,
5208
+ chain: {
5209
+ configured: chain.configured,
5210
+ get: chain.get,
5211
+ load: chain.load,
5212
+ subscribe: chain.subscribe
5213
+ },
5088
5214
  config,
5089
5215
  session: {
5090
5216
  authorize: session2.authorize,
5091
5217
  change: session2.change,
5092
5218
  exclusive: session2.exclusive,
5093
5219
  get: session2.get,
5094
- load: session2.load,
5220
+ // The stored chain loads beside the stored session, so a restored session reads its chain.
5221
+ // Once it loaded, a load is the session's alone, which adds no wait to the session's reads.
5222
+ load: async (options2) => {
5223
+ if (chain.loaded()) return session2.load(options2);
5224
+ const [loaded] = await Promise.all([
5225
+ session2.load(options2),
5226
+ chain.load().catch(() => void 0)
5227
+ ]);
5228
+ return loaded;
5229
+ },
5095
5230
  reload: session2.reload,
5096
5231
  renewing: session2.renewing,
5097
5232
  settled: session2.settled,
@@ -5147,7 +5282,7 @@ function create4(options = {}) {
5147
5282
  function connections2() {
5148
5283
  if (!connectionsOptions)
5149
5284
  return Promise.reject(new ConnectionsRequiredError());
5150
- attached ??= import("./Connections-DGFGVF35.js").then(
5285
+ attached ??= import("./Connections-YJB3F4KT.js").then(
5151
5286
  (module) => module.attach(config, connectionsOptions)
5152
5287
  );
5153
5288
  return attached;
@@ -5167,6 +5302,7 @@ function create4(options = {}) {
5167
5302
  ...parameters,
5168
5303
  renew: accessKey_option === void 0
5169
5304
  }),
5305
+ chain: { get: chain.get, subscribe: chain.subscribe },
5170
5306
  config,
5171
5307
  connection: {
5172
5308
  async disconnect() {
@@ -5237,7 +5373,25 @@ function create4(options = {}) {
5237
5373
  status: session2.status,
5238
5374
  subscribe: session2.subscribe
5239
5375
  },
5240
- signOut: (parameters) => signOut2({ everywhere: parameters?.everywhere })
5376
+ signOut: (parameters) => signOut2({ everywhere: parameters?.everywhere }),
5377
+ switchChain(parameters) {
5378
+ const valid2 = Number.isSafeInteger(parameters.chainId) && parameters.chainId > 0;
5379
+ const call = valid2 ? ++switches.count : switches.count;
5380
+ const run2 = switches.last.catch(() => void 0).then(
5381
+ () => switchChain(context, {
5382
+ ...parameters,
5383
+ account: async (chainId) => get(config, {
5384
+ accessToken: await accessToken2(),
5385
+ chainId,
5386
+ getFn: config.getFn
5387
+ }),
5388
+ latest: () => switches.count === call,
5389
+ select: chain.set
5390
+ })
5391
+ );
5392
+ if (valid2) switches.last = run2;
5393
+ return run2;
5394
+ }
5241
5395
  };
5242
5396
  async function signOut2(options2 = {}) {
5243
5397
  if (options2.everywhere && thirdParty(config.clientId))
@@ -5271,12 +5425,14 @@ var defaultUrl = "https://id.tempo.xyz";
5271
5425
  var reserved = /* @__PURE__ */ new Set([
5272
5426
  "account",
5273
5427
  "authorize",
5428
+ "chain",
5274
5429
  "config",
5275
5430
  "connection",
5276
5431
  "connections",
5277
5432
  "handler",
5278
5433
  "session",
5279
- "signOut"
5434
+ "signOut",
5435
+ "switchChain"
5280
5436
  ]);
5281
5437
 
5282
5438
  // ../../accounts/src/internal/Callback.ts
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  env,
3
3
  login
4
- } from "../chunk-5KYR4O7P.js";
5
- import "../chunk-MLNEONHA.js";
6
- import "../chunk-HIKQ4IBM.js";
4
+ } from "../chunk-6X7GAYK4.js";
5
+ import "../chunk-HAAICPJO.js";
6
+ import "../chunk-RS7QDWBO.js";
7
7
  import "../chunk-YW5DUQT3.js";
8
8
  import "../chunk-MLKGABMK.js";
9
9
 
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  env,
3
3
  remove
4
- } from "../chunk-5KYR4O7P.js";
5
- import "../chunk-MLNEONHA.js";
6
- import "../chunk-HIKQ4IBM.js";
4
+ } from "../chunk-6X7GAYK4.js";
5
+ import "../chunk-HAAICPJO.js";
6
+ import "../chunk-RS7QDWBO.js";
7
7
  import "../chunk-YW5DUQT3.js";
8
8
  import "../chunk-MLKGABMK.js";
9
9
 
@@ -2,9 +2,9 @@ import {
2
2
  env,
3
3
  signedOut,
4
4
  whoami
5
- } from "../chunk-5KYR4O7P.js";
6
- import "../chunk-MLNEONHA.js";
7
- import "../chunk-HIKQ4IBM.js";
5
+ } from "../chunk-6X7GAYK4.js";
6
+ import "../chunk-HAAICPJO.js";
7
+ import "../chunk-RS7QDWBO.js";
8
8
  import "../chunk-YW5DUQT3.js";
9
9
  import "../chunk-MLKGABMK.js";
10
10
 
@@ -4,7 +4,7 @@ import {
4
4
  expired2 as expired,
5
5
  from2 as from,
6
6
  toSession
7
- } from "./chunk-HIKQ4IBM.js";
7
+ } from "./chunk-RS7QDWBO.js";
8
8
  import "./chunk-MLKGABMK.js";
9
9
 
10
10
  // ../../accounts/src/plugins/dialog.ts
@@ -21,7 +21,17 @@ function dialog(options = {}) {
21
21
  if (par === void 0) return context.config;
22
22
  let config = configs.get(context.config);
23
23
  if (!config)
24
- configs.set(context.config, config = { ...context.config, par });
24
+ configs.set(
25
+ context.config,
26
+ // The copy keeps the getter of `chainId`, so it follows `switchChain`.
27
+ config = Object.assign(
28
+ Object.defineProperties(
29
+ {},
30
+ Object.getOwnPropertyDescriptors(context.config)
31
+ ),
32
+ { par }
33
+ )
34
+ );
25
35
  return config;
26
36
  }
27
37
  return from({
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "node": ">=24.21"
10
10
  },
11
11
  "name": "@tempoxyz/id",
12
- "version": "0.0.0-pr-723.sha-e431f51",
12
+ "version": "0.0.0-pr-721.sha-70e07db",
13
13
  "description": "The tempo-id CLI: sign in to Tempo ID, and call its API and the Admin API.",
14
14
  "type": "module",
15
15
  "bin": {