@pollar/core 0.8.1 → 0.9.0-rc.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/index.mjs CHANGED
@@ -1,3 +1,5 @@
1
+ import { sha256 as sha256$1 } from '@noble/hashes/sha2';
2
+
1
3
  var __create = Object.create;
2
4
  var __defProp = Object.defineProperty;
3
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -183,20 +185,6 @@ function defaultKeyManager(storage, apiKey) {
183
185
  return _factory(storage, apiKey);
184
186
  }
185
187
 
186
- // src/lib/sha256.ts
187
- async function sha256(data) {
188
- const buf = await crypto.subtle.digest("SHA-256", data);
189
- return new Uint8Array(buf);
190
- }
191
-
192
- // src/lib/api-key-hash.ts
193
- async function hashApiKey(apiKey) {
194
- const digest = await sha256(new TextEncoder().encode(apiKey));
195
- let hex = "";
196
- for (let i = 0; i < 4; i++) hex += digest[i].toString(16).padStart(2, "0");
197
- return hex;
198
- }
199
-
200
188
  // src/lib/base64url.ts
201
189
  var ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
202
190
  (() => {
@@ -233,6 +221,17 @@ function base64urlEncode(bytes) {
233
221
  function base64urlEncodeString(s) {
234
222
  return base64urlEncode(new TextEncoder().encode(s));
235
223
  }
224
+ async function sha256(data) {
225
+ return sha256$1(data);
226
+ }
227
+
228
+ // src/lib/api-key-hash.ts
229
+ async function hashApiKey(apiKey) {
230
+ const digest = await sha256(new TextEncoder().encode(apiKey));
231
+ let hex = "";
232
+ for (let i = 0; i < 4; i++) hex += digest[i].toString(16).padStart(2, "0");
233
+ return hex;
234
+ }
236
235
 
237
236
  // src/keys/thumbprint.ts
238
237
  async function computeJwkThumbprint(jwk) {
@@ -243,11 +242,14 @@ async function computeJwkThumbprint(jwk) {
243
242
  const digest = await sha256(new TextEncoder().encode(canonical));
244
243
  return base64urlEncode(digest);
245
244
  }
245
+ function toBase64url(value) {
246
+ return value.replace(/\+/g, "-").replace(/\//g, "_").replace(/[^A-Za-z0-9_-]/g, "");
247
+ }
246
248
  function canonicalEcJwk(jwk) {
247
249
  if (jwk.kty !== "EC" || jwk.crv !== "P-256" || typeof jwk.x !== "string" || typeof jwk.y !== "string") {
248
250
  throw new Error("[PollarClient:thumbprint] Source JWK is not an EC P-256 public key");
249
251
  }
250
- return { kty: "EC", crv: "P-256", x: jwk.x, y: jwk.y };
252
+ return { kty: "EC", crv: "P-256", x: toBase64url(jwk.x), y: toBase64url(jwk.y) };
251
253
  }
252
254
 
253
255
  // src/keys/web-crypto.ts
@@ -261,7 +263,7 @@ function openDb() {
261
263
  return;
262
264
  }
263
265
  const req = indexedDB.open(DB_NAME, DB_VERSION);
264
- req.onerror = () => reject(req.error ?? new Error("IDB open failed"));
266
+ req.onerror = () => reject(req.error ?? new Error("[PollarClient:keys] IDB open failed"));
265
267
  req.onsuccess = () => resolve(req.result);
266
268
  req.onupgradeneeded = () => {
267
269
  const db = req.result;
@@ -274,7 +276,7 @@ function openDb() {
274
276
  function awaitTx(req) {
275
277
  return new Promise((resolve, reject) => {
276
278
  req.onsuccess = () => resolve(req.result);
277
- req.onerror = () => reject(req.error ?? new Error("IDB request failed"));
279
+ req.onerror = () => reject(req.error ?? new Error("[PollarClient:keys] IDB request failed"));
278
280
  });
279
281
  }
280
282
  async function dbGet(key) {
@@ -369,10 +371,39 @@ var WebCryptoKeyManager = class {
369
371
  }
370
372
  }
371
373
  this.keyPair = pair;
372
- const exported = await globalThis.crypto.subtle.exportKey("jwk", pair.publicKey);
373
- this.publicJwk = canonicalEcJwk(exported);
374
+ this.publicJwk = await this._exportPublicJwk(pair.publicKey);
374
375
  this.thumbprint = await computeJwkThumbprint(this.publicJwk);
375
376
  }
377
+ /**
378
+ * Derive the public JWK from a `CryptoKey`. Prefers the `'raw'` export (the
379
+ * 65-byte uncompressed point `0x04 || X(32) || Y(32)`) and base64url-encodes
380
+ * the coordinates ourselves — that sidesteps polyfills whose `exportKey('jwk')`
381
+ * emits non-base64url `x`/`y` (standard base64, `=` padding, or — as seen with
382
+ * `react-native-quick-crypto` — a stray `.`). Real browsers and most polyfills
383
+ * support `'raw'` for public EC keys.
384
+ *
385
+ * Falls back to the `'jwk'` export (normalized via `canonicalEcJwk`) if `'raw'`
386
+ * is unsupported or returns an unexpected shape, so this can't regress on a
387
+ * runtime that only implements the JWK path. Both routes yield identical
388
+ * coordinate bytes, so the `cnf.jkt` thumbprint is unchanged either way.
389
+ */
390
+ async _exportPublicJwk(publicKey) {
391
+ try {
392
+ const raw = new Uint8Array(await globalThis.crypto.subtle.exportKey("raw", publicKey));
393
+ if (raw.length !== 65 || raw[0] !== 4) {
394
+ throw new Error(`[PollarClient:keys] Unexpected raw EC point (len=${raw.length}, tag=${raw[0]})`);
395
+ }
396
+ return {
397
+ kty: "EC",
398
+ crv: "P-256",
399
+ x: base64urlEncode(raw.slice(1, 33)),
400
+ y: base64urlEncode(raw.slice(33, 65))
401
+ };
402
+ } catch {
403
+ const jwk = await globalThis.crypto.subtle.exportKey("jwk", publicKey);
404
+ return canonicalEcJwk(jwk);
405
+ }
406
+ }
376
407
  async reset() {
377
408
  try {
378
409
  if (this.apiKeyHash) await dbDelete(this.apiKeyHash);
@@ -1130,6 +1161,9 @@ function defaultStorage(options = {}) {
1130
1161
  return createLocalStorageAdapter(options);
1131
1162
  }
1132
1163
 
1164
+ // src/version.ts
1165
+ var POLLAR_CORE_VERSION = "0.9.0-rc.0" ;
1166
+
1133
1167
  // src/visibility/noop.ts
1134
1168
  function createNoopVisibilityProvider() {
1135
1169
  return {
@@ -1194,6 +1228,7 @@ var AUTH_ERROR_CODES = {
1194
1228
  WALLET_CONNECT_FAILED: "WALLET_CONNECT_FAILED",
1195
1229
  WALLET_AUTH_FAILED: "WALLET_AUTH_FAILED",
1196
1230
  WALLET_RESOLVER_TIMEOUT: "WALLET_RESOLVER_TIMEOUT",
1231
+ PASSKEY_FAILED: "PASSKEY_FAILED",
1197
1232
  UNEXPECTED_ERROR: "UNEXPECTED_ERROR"
1198
1233
  };
1199
1234
  var PollarFlowError = class extends Error {
@@ -1239,7 +1274,7 @@ var FreighterAdapter = class {
1239
1274
  if (!userInfo?.publicKey) {
1240
1275
  throw new Error("Failed to get user information from Freighter");
1241
1276
  }
1242
- return { address: userInfo.publicKey, publicKey: userInfo.publicKey };
1277
+ return { address: userInfo.publicKey };
1243
1278
  }
1244
1279
  async disconnect() {
1245
1280
  }
@@ -1277,6 +1312,19 @@ var FreighterAdapter = class {
1277
1312
  };
1278
1313
 
1279
1314
  // src/wallets/AlbedoAdapter.ts
1315
+ var PUBLIC_PASSPHRASE = "Public Global Stellar Network ; September 2015";
1316
+ var TESTNET_PASSPHRASE = "Test SDF Network ; September 2015";
1317
+ function albedoNetwork(options, fallback) {
1318
+ switch (options?.networkPassphrase) {
1319
+ case PUBLIC_PASSPHRASE:
1320
+ return "public";
1321
+ case TESTNET_PASSPHRASE:
1322
+ return "testnet";
1323
+ }
1324
+ if (options?.network === "public" || options?.network === "mainnet") return "public";
1325
+ if (options?.network === "testnet") return "testnet";
1326
+ return fallback;
1327
+ }
1280
1328
  function openAlbedoPopup(url) {
1281
1329
  const popup = window.open(url, "albedo", "width=420,height=720,resizable=yes,scrollbars=yes");
1282
1330
  if (!popup) {
@@ -1315,7 +1363,13 @@ function waitForAlbedoResult() {
1315
1363
  });
1316
1364
  }
1317
1365
  var AlbedoAdapter = class {
1318
- constructor() {
1366
+ /**
1367
+ * Network used for `connect` and `signAuthEntry` (which carry no per-call
1368
+ * network) and as the fallback for `signTransaction`. Defaults to `'testnet'`
1369
+ * to preserve the previous behavior when constructed with no argument.
1370
+ */
1371
+ constructor(network = "testnet") {
1372
+ this.network = network;
1319
1373
  this.type = "albedo" /* ALBEDO */;
1320
1374
  }
1321
1375
  async isAvailable() {
@@ -1325,7 +1379,7 @@ var AlbedoAdapter = class {
1325
1379
  const url = new URL("https://albedo.link");
1326
1380
  url.searchParams.set("intent", "public-key");
1327
1381
  url.searchParams.set("app_name", "Pollar");
1328
- url.searchParams.set("network", "testnet");
1382
+ url.searchParams.set("network", this.network);
1329
1383
  url.searchParams.set("callback", `${window.location.origin}/albedo-callback`);
1330
1384
  url.searchParams.set("origin", window.location.origin);
1331
1385
  openAlbedoPopup(url.toString());
@@ -1333,7 +1387,7 @@ var AlbedoAdapter = class {
1333
1387
  if (!result.pubkey) {
1334
1388
  throw new Error("Albedo connection rejected");
1335
1389
  }
1336
- return { address: result.pubkey, publicKey: result.pubkey };
1390
+ return { address: result.pubkey };
1337
1391
  }
1338
1392
  async disconnect() {
1339
1393
  }
@@ -1343,12 +1397,12 @@ var AlbedoAdapter = class {
1343
1397
  async getNetwork() {
1344
1398
  throw new Error("Albedo does not expose network");
1345
1399
  }
1346
- async signTransaction(xdr, _options) {
1400
+ async signTransaction(xdr, options) {
1347
1401
  const url = new URL("https://albedo.link");
1348
1402
  url.searchParams.set("intent", "tx");
1349
1403
  url.searchParams.set("xdr", xdr);
1350
1404
  url.searchParams.set("app_name", "Pollar");
1351
- url.searchParams.set("network", "testnet");
1405
+ url.searchParams.set("network", albedoNetwork(options, this.network));
1352
1406
  url.searchParams.set("callback", window.location.href);
1353
1407
  url.searchParams.set("origin", window.location.origin);
1354
1408
  window.location.href = url.toString();
@@ -1361,7 +1415,7 @@ var AlbedoAdapter = class {
1361
1415
  url.searchParams.set("intent", "sign-auth-entry");
1362
1416
  url.searchParams.set("xdr", entryXdr);
1363
1417
  url.searchParams.set("app_name", "Pollar");
1364
- url.searchParams.set("network", "testnet");
1418
+ url.searchParams.set("network", this.network);
1365
1419
  url.searchParams.set("callback", window.location.href);
1366
1420
  url.searchParams.set("origin", window.location.origin);
1367
1421
  window.location.href = url.toString();
@@ -1448,8 +1502,12 @@ function isValidSession(value) {
1448
1502
  return false;
1449
1503
  }
1450
1504
  const w = wallet;
1451
- if (w["publicKey"] !== null && !isBoundedString(w["publicKey"], MAX_WALLET_PUBLIC_KEY)) {
1452
- console.warn("[PollarClient:session] Invalid session \u2014 wallet.publicKey must be string|null");
1505
+ if (w["type"] !== "custodial" && w["type"] !== "smart" && w["type"] !== "external") {
1506
+ console.warn("[PollarClient:session] Invalid session \u2014 wallet.type must be custodial|smart|external");
1507
+ return false;
1508
+ }
1509
+ if (w["address"] !== null && !isBoundedString(w["address"], MAX_WALLET_PUBLIC_KEY)) {
1510
+ console.warn("[PollarClient:session] Invalid session \u2014 wallet.address must be string|null");
1453
1511
  return false;
1454
1512
  }
1455
1513
  if (w["existsOnStellar"] !== void 0 && typeof w["existsOnStellar"] !== "boolean") {
@@ -1460,6 +1518,10 @@ function isValidSession(value) {
1460
1518
  console.warn("[PollarClient:session] Invalid session \u2014 wallet.createdAt must be a finite number if present");
1461
1519
  return false;
1462
1520
  }
1521
+ if (w["linkedAt"] !== void 0 && (typeof w["linkedAt"] !== "number" || !Number.isFinite(w["linkedAt"]))) {
1522
+ console.warn("[PollarClient:session] Invalid session \u2014 wallet.linkedAt must be a finite number if present");
1523
+ return false;
1524
+ }
1463
1525
  return true;
1464
1526
  }
1465
1527
  async function readStorage(storage, apiKeyHash) {
@@ -1467,6 +1529,12 @@ async function readStorage(storage, apiKeyHash) {
1467
1529
  if (!raw) return null;
1468
1530
  try {
1469
1531
  const session = JSON.parse(raw);
1532
+ if (typeof session === "object" && session !== null) {
1533
+ const w = session.wallet;
1534
+ if (w && w["address"] == null && typeof w["publicKey"] === "string") {
1535
+ w["address"] = w["publicKey"];
1536
+ }
1537
+ }
1470
1538
  if (!isValidSession(session)) {
1471
1539
  await storage.remove(sessionStorageKey(apiKeyHash));
1472
1540
  console.warn("[PollarClient:session] Stored session is invalid \u2014 clearing storage");
@@ -1557,7 +1625,7 @@ async function streamUntilFound(api, clientSessionId, check, retryDelayMs = 200,
1557
1625
  }));
1558
1626
  } catch (e) {
1559
1627
  if (e instanceof Error && e.name === "AbortError") throw e;
1560
- console.warn(e);
1628
+ console.warn("[PollarClient:stream] session-status request failed; will retry", e);
1561
1629
  }
1562
1630
  if (error || !data) {
1563
1631
  await sleep(backoff);
@@ -1597,7 +1665,7 @@ async function streamUntilFound(api, clientSessionId, check, retryDelayMs = 200,
1597
1665
  } catch (e) {
1598
1666
  if (e instanceof Error && e.name === "AbortError") throw e;
1599
1667
  if (e instanceof SessionStatusError) throw e;
1600
- console.warn(e);
1668
+ console.warn("[PollarClient:stream] session-status stream read failed; will retry", e);
1601
1669
  } finally {
1602
1670
  reader.releaseLock();
1603
1671
  }
@@ -1625,7 +1693,7 @@ async function pollUntilFound(baseUrl, clientSessionId, check, intervalMs = 500,
1625
1693
  envelope = await response.json().catch(() => null);
1626
1694
  } catch (e) {
1627
1695
  if (e instanceof Error && e.name === "AbortError") throw e;
1628
- console.warn(e);
1696
+ console.warn("[PollarClient:stream] session-status poll failed; will retry", e);
1629
1697
  }
1630
1698
  if (httpStatus === 404 || envelope?.code === "INVALID_CLIENT_SESSION_ID") {
1631
1699
  throw new SessionStatusError("INVALID_CLIENT_SESSION_ID");
@@ -1829,6 +1897,55 @@ async function loginOAuth(provider, deps) {
1829
1897
  await authenticate(clientSessionId, deps);
1830
1898
  }
1831
1899
 
1900
+ // src/client/auth/passkeyFlow.ts
1901
+ async function loginSmartWallet(deps) {
1902
+ const { api, signal, setAuthState, passkey } = deps;
1903
+ if (!passkey) {
1904
+ setAuthState({
1905
+ step: "error",
1906
+ previousStep: "creating_session",
1907
+ message: "Passkey support is not configured",
1908
+ errorCode: AUTH_ERROR_CODES.PASSKEY_FAILED
1909
+ });
1910
+ return;
1911
+ }
1912
+ const clientSessionId = await createAuthSession(deps);
1913
+ if (!clientSessionId) return;
1914
+ try {
1915
+ const { data: challengeData } = await api.POST("/auth/passkey/challenge", {
1916
+ body: { clientSessionId },
1917
+ signal
1918
+ });
1919
+ const challenge = challengeData?.content?.challenge;
1920
+ if (!challengeData?.success || !challenge) {
1921
+ return failPasskey(setAuthState, "Failed to start passkey");
1922
+ }
1923
+ setAuthState({ step: "creating_passkey" });
1924
+ const ceremony = await passkey({ challenge });
1925
+ const response = ceremony.response;
1926
+ if (ceremony.kind === "register") {
1927
+ setAuthState({ step: "deploying_smart_account" });
1928
+ const { data } = await api.POST("/auth/passkey/register", {
1929
+ body: { clientSessionId, response },
1930
+ signal
1931
+ });
1932
+ if (!data?.success) return failPasskey(setAuthState, "Passkey registration failed");
1933
+ } else {
1934
+ const { data } = await api.POST("/auth/passkey/login", {
1935
+ body: { clientSessionId, response },
1936
+ signal
1937
+ });
1938
+ if (!data?.success) return failPasskey(setAuthState, "Passkey authentication failed");
1939
+ }
1940
+ } catch {
1941
+ return failPasskey(setAuthState, "Passkey login failed");
1942
+ }
1943
+ await authenticate(clientSessionId, deps);
1944
+ }
1945
+ function failPasskey(setAuthState, message) {
1946
+ setAuthState({ step: "error", previousStep: "creating_passkey", message, errorCode: AUTH_ERROR_CODES.PASSKEY_FAILED });
1947
+ }
1948
+
1832
1949
  // src/client/auth/walletFlow.ts
1833
1950
  function withSignal(promise, signal) {
1834
1951
  return Promise.race([
@@ -1855,12 +1972,12 @@ async function loginWallet(type, deps) {
1855
1972
  setAuthState({ step: "wallet_not_installed", walletType: type });
1856
1973
  return;
1857
1974
  }
1858
- const { publicKey } = await withSignal(adapter.connect(), signal);
1859
- connectedWallet = publicKey;
1975
+ const { address } = await withSignal(adapter.connect(), signal);
1976
+ connectedWallet = address;
1860
1977
  deps.storeWalletAdapter(adapter, type);
1861
1978
  setAuthState({ step: "authenticating_wallet" });
1862
1979
  const { data: walletData, error: walletError } = await api.POST("/auth/wallet", {
1863
- body: { clientSessionId, walletAddress: publicKey },
1980
+ body: { clientSessionId, walletAddress: address },
1864
1981
  signal
1865
1982
  });
1866
1983
  if (walletError || !walletData?.success) {
@@ -1925,8 +2042,12 @@ var PollarClient = class {
1925
2042
  this._transactionStateListeners = /* @__PURE__ */ new Set();
1926
2043
  this._txHistoryState = { step: "idle" };
1927
2044
  this._txHistoryStateListeners = /* @__PURE__ */ new Set();
2045
+ this._sessionsState = { step: "idle" };
2046
+ this._sessionsStateListeners = /* @__PURE__ */ new Set();
1928
2047
  this._walletBalanceState = { step: "idle" };
1929
2048
  this._walletBalanceStateListeners = /* @__PURE__ */ new Set();
2049
+ this._enabledAssetsState = { step: "idle" };
2050
+ this._enabledAssetsStateListeners = /* @__PURE__ */ new Set();
1930
2051
  this._authState = { step: "idle" };
1931
2052
  this._authStateListeners = /* @__PURE__ */ new Set();
1932
2053
  this._networkState = { step: "idle" };
@@ -1942,6 +2063,8 @@ var PollarClient = class {
1942
2063
  this._storageDegradeListeners = /* @__PURE__ */ new Set();
1943
2064
  this._walletAdapter = null;
1944
2065
  this._loginController = null;
2066
+ /** Aborts an in-flight `/auth/session/resume` on destroy() or re-trigger. */
2067
+ this._resumeController = null;
1945
2068
  this.apiKey = config.apiKey;
1946
2069
  this.id = randomUUID();
1947
2070
  this.basePath = `${config.baseUrl || "https://sdk.api.pollar.xyz"}/v1`;
@@ -1954,6 +2077,8 @@ var PollarClient = class {
1954
2077
  this._keyManager = config.keyManager ?? defaultKeyManager(this._storage, config.apiKey);
1955
2078
  this._walletAdapterResolver = config.walletAdapter ?? null;
1956
2079
  this._walletResolverTimeoutMs = config.walletResolverTimeoutMs ?? 5e3;
2080
+ this._passkey = config.passkey ?? null;
2081
+ this._passkeySign = config.passkeySign ?? null;
1957
2082
  this._deviceLabel = config.deviceLabel;
1958
2083
  this._visibilityProvider = config.visibilityProvider ?? defaultVisibilityProvider();
1959
2084
  this._maxIdleMs = config.maxIdleMs;
@@ -1967,7 +2092,9 @@ var PollarClient = class {
1967
2092
  this._initialized = Promise.resolve();
1968
2093
  return;
1969
2094
  }
1970
- console.info(`[PollarClient] Initialized \u2014 endpoint: ${this.basePath}, network: ${this._networkState.network}`);
2095
+ console.info(
2096
+ `[PollarClient] Initialized v${POLLAR_CORE_VERSION} \u2014 endpoint: ${this.basePath}, network: ${this._networkState.network}`
2097
+ );
1971
2098
  this._initialized = this._initialize();
1972
2099
  }
1973
2100
  /**
@@ -2005,7 +2132,11 @@ var PollarClient = class {
2005
2132
  }
2006
2133
  await this._restoreSession();
2007
2134
  this._visibilityUnsubscribe = this._visibilityProvider.onChange((visible) => {
2008
- if (visible) void this._maybeProactiveRefresh();
2135
+ if (!visible) return;
2136
+ void this._maybeProactiveRefresh();
2137
+ if (this._authState.step === "authenticated" && !this._authState.verified) {
2138
+ void this._resume();
2139
+ }
2009
2140
  });
2010
2141
  }
2011
2142
  /** Detach the cross-tab storage listener and abort any in-flight login. */
@@ -2016,6 +2147,8 @@ var PollarClient = class {
2016
2147
  }
2017
2148
  this._loginController?.abort();
2018
2149
  this._loginController = null;
2150
+ this._resumeController?.abort();
2151
+ this._resumeController = null;
2019
2152
  this._clearRefreshTimer();
2020
2153
  if (this._visibilityUnsubscribe) {
2021
2154
  this._visibilityUnsubscribe();
@@ -2030,7 +2163,9 @@ var PollarClient = class {
2030
2163
  request.headers.set("x-pollar-api-key", self.apiKey);
2031
2164
  self._lastRequestAt = Date.now();
2032
2165
  await self._initialized;
2033
- if (request.body !== null) {
2166
+ const cacheMethod = request.method.toUpperCase();
2167
+ const cacheBodyAllowed = cacheMethod !== "GET" && cacheMethod !== "HEAD";
2168
+ if (cacheBodyAllowed && request.body != null) {
2034
2169
  try {
2035
2170
  self._requestBodyCache.set(request, await request.clone().arrayBuffer());
2036
2171
  } catch (err) {
@@ -2117,7 +2252,9 @@ var PollarClient = class {
2117
2252
  }
2118
2253
  }
2119
2254
  }
2120
- const cachedBody = this._requestBodyCache.get(originalRequest);
2255
+ const retryMethod = originalRequest.method.toUpperCase();
2256
+ const retryBodyAllowed = retryMethod !== "GET" && retryMethod !== "HEAD";
2257
+ const cachedBody = retryBodyAllowed ? this._requestBodyCache.get(originalRequest) : void 0;
2121
2258
  const retried = new Request(originalRequest.url, {
2122
2259
  method: originalRequest.method,
2123
2260
  headers,
@@ -2161,19 +2298,26 @@ var PollarClient = class {
2161
2298
  throw err;
2162
2299
  }
2163
2300
  if (error || !data) {
2164
- console.warn("[PollarClient] /auth/refresh returned error", { error });
2301
+ console.error("[PollarClient] /auth/refresh returned error", { error });
2165
2302
  await this._clearSession();
2166
2303
  throw new Error("Refresh failed");
2167
2304
  }
2168
2305
  const successData = data;
2169
2306
  if (!successData.success || !successData.content?.token) {
2170
- console.warn("[PollarClient] /auth/refresh response malformed", successData);
2307
+ console.error("[PollarClient] /auth/refresh response malformed", {
2308
+ success: successData.success,
2309
+ hasToken: !!successData.content?.token
2310
+ });
2171
2311
  await this._clearSession();
2172
2312
  throw new Error("Refresh response malformed");
2173
2313
  }
2174
2314
  const newToken = successData.content.token;
2175
2315
  if (typeof newToken.accessToken !== "string" || typeof newToken.refreshToken !== "string" || typeof newToken.expiresAt !== "number") {
2176
- console.warn("[PollarClient] /auth/refresh token shape invalid", newToken);
2316
+ console.error("[PollarClient] /auth/refresh token shape invalid", {
2317
+ accessToken: typeof newToken.accessToken,
2318
+ refreshToken: typeof newToken.refreshToken,
2319
+ expiresAt: typeof newToken.expiresAt
2320
+ });
2177
2321
  await this._clearSession();
2178
2322
  throw new Error("Refresh response token shape invalid");
2179
2323
  }
@@ -2367,6 +2511,19 @@ var PollarClient = class {
2367
2511
  const controller = this._newController();
2368
2512
  loginWallet(type, this._flowDeps(controller.signal)).catch((err) => this._handleFlowError(err));
2369
2513
  }
2514
+ /**
2515
+ * "Smart Wallet" login: runs the passkey (WebAuthn) ceremony and, for a new
2516
+ * user, creates a sponsored smart-account C-address. Requires the `passkey`
2517
+ * ceremony to be configured (e.g. via `@pollar/react`).
2518
+ */
2519
+ loginSmartWallet() {
2520
+ if (!isClientRuntime) {
2521
+ warnServerSide("loginSmartWallet");
2522
+ return;
2523
+ }
2524
+ const controller = this._newController();
2525
+ loginSmartWallet(this._flowDeps(controller.signal)).catch((err) => this._handleFlowError(err));
2526
+ }
2370
2527
  // ─── Cancel ───────────────────────────────────────────────────────────────
2371
2528
  cancelLogin() {
2372
2529
  this._loginController?.abort();
@@ -2429,6 +2586,29 @@ var PollarClient = class {
2429
2586
  }
2430
2587
  return data.content.sessions;
2431
2588
  }
2589
+ getSessionsState() {
2590
+ return this._sessionsState;
2591
+ }
2592
+ onSessionsStateChange(cb) {
2593
+ this._sessionsStateListeners.add(cb);
2594
+ cb(this._sessionsState);
2595
+ return () => this._sessionsStateListeners.delete(cb);
2596
+ }
2597
+ /**
2598
+ * Fire-and-forget variant of {@link listSessions} that drives the observable
2599
+ * `SessionsState` store instead of returning the array. UI layers subscribe
2600
+ * via `onSessionsStateChange` and stay pure readers — mirrors `fetchTxHistory`.
2601
+ */
2602
+ async fetchSessions() {
2603
+ this._setSessionsState({ step: "loading" });
2604
+ try {
2605
+ const sessions = await this.listSessions();
2606
+ this._setSessionsState({ step: "loaded", sessions });
2607
+ } catch (err) {
2608
+ const message = err instanceof Error ? err.message : "Failed to load sessions";
2609
+ this._setSessionsState({ step: "error", message });
2610
+ }
2611
+ }
2432
2612
  /**
2433
2613
  * Revoke a specific refresh-token family (a single device session). Use
2434
2614
  * `listSessions` to enumerate the familyIds. Revoking the current session
@@ -2505,16 +2685,19 @@ var PollarClient = class {
2505
2685
  cb(this._walletBalanceState);
2506
2686
  return () => this._walletBalanceStateListeners.delete(cb);
2507
2687
  }
2508
- async refreshBalance(publicKey) {
2509
- const pk = publicKey ?? this._session?.wallet?.publicKey;
2510
- if (!pk) {
2688
+ /**
2689
+ * Refreshes the balances of the authenticated user's OWN wallet. The wallet
2690
+ * and network are resolved server-side from the session — no arguments. Drives
2691
+ * `walletBalanceState`. For an arbitrary wallet, use {@link getWalletBalance}.
2692
+ */
2693
+ async refreshBalance() {
2694
+ if (!this._session?.wallet?.address) {
2511
2695
  this._setWalletBalanceState({ step: "error", message: "No wallet connected" });
2512
2696
  return;
2513
2697
  }
2514
2698
  this._setWalletBalanceState({ step: "loading" });
2515
2699
  try {
2516
- const network = this.getNetwork();
2517
- const { data, error } = await this._api.GET("/wallet/balance", { params: { query: { publicKey: pk, network } } });
2700
+ const { data, error } = await this._api.GET("/wallet/balance");
2518
2701
  if (!error && data?.success && data.content) {
2519
2702
  this._setWalletBalanceState({ step: "loaded", data: data.content });
2520
2703
  } else {
@@ -2524,6 +2707,53 @@ var PollarClient = class {
2524
2707
  this._setWalletBalanceState({ step: "error", message: "Failed to load balance" });
2525
2708
  }
2526
2709
  }
2710
+ /**
2711
+ * General-purpose balance lookup for ANY wallet on ANY network — not scoped
2712
+ * to this application. Enumerates the account's real on-chain holdings via
2713
+ * Horizon (server-side) and returns the data directly (no reactive state).
2714
+ * `network` defaults to the client's current network.
2715
+ */
2716
+ async getWalletBalance(publicKey, network) {
2717
+ const { data, error } = await this._api.GET("/wallet/{publicKey}/balance", {
2718
+ params: { path: { publicKey }, query: { network: network ?? this.getNetwork() } }
2719
+ });
2720
+ if (error || !data?.success || !data.content) {
2721
+ throw new Error("[PollarClient] Failed to load wallet balance");
2722
+ }
2723
+ return data.content;
2724
+ }
2725
+ // ─── Enabled assets ───────────────────────────────────────────────────────
2726
+ getEnabledAssetsState() {
2727
+ return this._enabledAssetsState;
2728
+ }
2729
+ onEnabledAssetsStateChange(cb) {
2730
+ this._enabledAssetsStateListeners.add(cb);
2731
+ cb(this._enabledAssetsState);
2732
+ return () => this._enabledAssetsStateListeners.delete(cb);
2733
+ }
2734
+ /**
2735
+ * Loads the application's enabled assets paired with the authenticated
2736
+ * wallet's on-chain trustline state — so the SDK knows which trustlines still
2737
+ * need to be added. Wallet and network are resolved server-side from the
2738
+ * session. Drives `enabledAssetsState`; mirrors {@link refreshBalance}.
2739
+ */
2740
+ async refreshAssets() {
2741
+ if (!this._session?.wallet?.address) {
2742
+ this._setEnabledAssetsState({ step: "error", message: "No wallet connected" });
2743
+ return;
2744
+ }
2745
+ this._setEnabledAssetsState({ step: "loading" });
2746
+ try {
2747
+ const { data, error } = await this._api.GET("/wallet/assets");
2748
+ if (!error && data?.success && data.content) {
2749
+ this._setEnabledAssetsState({ step: "loaded", data: data.content });
2750
+ } else {
2751
+ this._setEnabledAssetsState({ step: "error", message: "Failed to load assets" });
2752
+ }
2753
+ } catch {
2754
+ this._setEnabledAssetsState({ step: "error", message: "Failed to load assets" });
2755
+ }
2756
+ }
2527
2757
  // ─── Transactions ─────────────────────────────────────────────────────────
2528
2758
  /**
2529
2759
  * Builds an unsigned XDR. Drives `_setTransactionState` for modal-style UIs
@@ -2531,14 +2761,14 @@ var PollarClient = class {
2531
2761
  * inspect the result without subscribing to state changes.
2532
2762
  */
2533
2763
  async buildTx(operation, params, options) {
2534
- if (!this._session?.wallet?.publicKey) {
2764
+ if (!this._session?.wallet?.address) {
2535
2765
  const details = "No wallet connected";
2536
2766
  this._setTransactionState({ step: "error", phase: "building", details });
2537
2767
  return { status: "error", details };
2538
2768
  }
2539
2769
  const body = {
2540
2770
  network: this.getNetwork(),
2541
- publicKey: this._session.wallet.publicKey,
2771
+ address: this._session.wallet.address,
2542
2772
  operation,
2543
2773
  params,
2544
2774
  options: options ?? {}
@@ -2579,7 +2809,7 @@ var PollarClient = class {
2579
2809
  const buildData = this._currentBuildData();
2580
2810
  this._setTransactionState({ step: "signing", ...buildData && { buildData } });
2581
2811
  if (this._walletAdapter) {
2582
- const accountToSign = this._session?.wallet?.publicKey;
2812
+ const accountToSign = this._session?.wallet?.address;
2583
2813
  const signOpts = accountToSign ? { networkPassphrase: this._networkPassphrase(), accountToSign } : { networkPassphrase: this._networkPassphrase() };
2584
2814
  try {
2585
2815
  const { signedTxXdr } = await this._walletAdapter.signTransaction(unsignedXdr, signOpts);
@@ -2600,10 +2830,10 @@ var PollarClient = class {
2600
2830
  return { status: "error", ...details && { details } };
2601
2831
  }
2602
2832
  }
2603
- const publicKey = this._session?.wallet?.publicKey ?? "";
2833
+ const address = this._session?.wallet?.address ?? "";
2604
2834
  try {
2605
2835
  const { data, error } = await this._api.POST("/tx/sign", {
2606
- body: { network: this.getNetwork(), publicKey, unsignedXdr }
2836
+ body: { network: this.getNetwork(), address, unsignedXdr }
2607
2837
  });
2608
2838
  if (!error && data?.success && data.content?.signedXdr) {
2609
2839
  const { signedXdr, idempotencyKey } = data.content;
@@ -2656,12 +2886,12 @@ var PollarClient = class {
2656
2886
  const buildData = this._currentBuildData();
2657
2887
  const outcomeExtra = buildData ? { buildData } : {};
2658
2888
  this._setTransactionState({ step: "submitting", signedXdr, ...buildData && { buildData } });
2659
- const publicKey = this._session?.wallet?.publicKey ?? "";
2889
+ const address = this._session?.wallet?.address ?? "";
2660
2890
  try {
2661
2891
  const { data, error } = await this._api.POST("/tx/submit", {
2662
2892
  body: {
2663
2893
  network: this.getNetwork(),
2664
- publicKey,
2894
+ address,
2665
2895
  signedXdr,
2666
2896
  ...opts?.submissionToken && { idempotencyKey: opts.submissionToken }
2667
2897
  }
@@ -2721,6 +2951,19 @@ var PollarClient = class {
2721
2951
  * `success` (ledger-confirmed), or `error[phase: 'signing-submitting']`.
2722
2952
  */
2723
2953
  async signAndSubmitTx(unsignedXdr) {
2954
+ if (this._session?.wallet?.type === "smart") {
2955
+ const buildData2 = this._currentBuildData();
2956
+ if (!buildData2?.smart) {
2957
+ const details = "no prepared smart transaction; call buildTx first";
2958
+ this._setTransactionState({ step: "error", phase: "signing", details });
2959
+ return { status: "error", details };
2960
+ }
2961
+ return this._signSubmitSmart(buildData2);
2962
+ }
2963
+ if (!unsignedXdr) {
2964
+ this._setTransactionState({ step: "error", phase: "signing", details: "missing unsigned transaction" });
2965
+ return { status: "error", details: "missing unsigned transaction" };
2966
+ }
2724
2967
  if (this._walletAdapter) {
2725
2968
  const signed = await this.signTx(unsignedXdr);
2726
2969
  if (signed.status === "error") {
@@ -2738,7 +2981,7 @@ var PollarClient = class {
2738
2981
  this._setTransactionState({ step: "signing-submitting", ...buildData && { buildData } });
2739
2982
  const body = {
2740
2983
  network: this.getNetwork(),
2741
- publicKey: this._session?.wallet?.publicKey ?? "",
2984
+ address: this._session?.wallet?.address ?? "",
2742
2985
  unsignedXdr
2743
2986
  };
2744
2987
  try {
@@ -2807,14 +3050,20 @@ var PollarClient = class {
2807
3050
  * `signTx`, and `submitTx` separately instead.
2808
3051
  */
2809
3052
  async buildAndSignAndSubmitTx(operation, params, options) {
3053
+ if (this._session?.wallet?.type === "smart") {
3054
+ return this._runSmartTx(operation, params, options);
3055
+ }
2810
3056
  if (this._walletAdapter) {
2811
3057
  const built = await this.buildTx(operation, params, options);
2812
3058
  if (built.status === "error") {
2813
3059
  return { status: "error", ...built.details && { details: built.details } };
2814
3060
  }
3061
+ if (!built.buildData.unsignedXdr) {
3062
+ return { status: "error", details: "build returned no unsigned transaction" };
3063
+ }
2815
3064
  return this.signAndSubmitTx(built.buildData.unsignedXdr);
2816
3065
  }
2817
- if (!this._session?.wallet?.publicKey) {
3066
+ if (!this._session?.wallet?.address) {
2818
3067
  this._setTransactionState({ step: "error", phase: "building-signing-submitting", details: "No wallet connected" });
2819
3068
  return { status: "error", details: "No wallet connected" };
2820
3069
  }
@@ -2823,7 +3072,7 @@ var PollarClient = class {
2823
3072
  const { data, error } = await this._api.POST("/tx/build-sign-submit", {
2824
3073
  body: {
2825
3074
  network: this.getNetwork(),
2826
- publicKey: this._session.wallet.publicKey,
3075
+ address: this._session.wallet.address,
2827
3076
  operation,
2828
3077
  params,
2829
3078
  options: options ?? {}
@@ -2867,6 +3116,113 @@ var PollarClient = class {
2867
3116
  async runTx(operation, params, options) {
2868
3117
  return this.buildAndSignAndSubmitTx(operation, params, options);
2869
3118
  }
3119
+ /**
3120
+ * Smart-wallet (passkey / C-address) transaction: build (server prepares the
3121
+ * SAC transfer + returns the auth digest) → sign the digest with the passkey
3122
+ * → submit (server assembles the signed auth entry and broadcasts; the
3123
+ * sponsor pays the fee). State machine: building → built → signing →
3124
+ * submitting → success.
3125
+ */
3126
+ async _runSmartTx(operation, params, options) {
3127
+ const address = this._session?.wallet?.address;
3128
+ if (!address) {
3129
+ this._setTransactionState({ step: "error", phase: "building", details: "No wallet connected" });
3130
+ return { status: "error", details: "No wallet connected" };
3131
+ }
3132
+ if (!this._passkeySign) {
3133
+ const details = "Passkey signer not configured";
3134
+ this._setTransactionState({ step: "error", phase: "signing", details });
3135
+ return { status: "error", details };
3136
+ }
3137
+ this._setTransactionState({ step: "building" });
3138
+ let buildData;
3139
+ try {
3140
+ const body = {
3141
+ network: this.getNetwork(),
3142
+ address,
3143
+ operation,
3144
+ params,
3145
+ options: options ?? {}
3146
+ };
3147
+ const { data, error } = await this._api.POST("/tx/build", { body });
3148
+ if (error || !data?.success || !data.content?.smart) {
3149
+ const details = error?.details ?? "Failed to build transaction";
3150
+ this._setTransactionState({ step: "error", phase: "building", details });
3151
+ return { status: "error", details };
3152
+ }
3153
+ buildData = data.content;
3154
+ } catch (err) {
3155
+ const details = err instanceof Error ? err.message : void 0;
3156
+ this._setTransactionState({ step: "error", phase: "building", ...details && { details } });
3157
+ return { status: "error", ...details && { details } };
3158
+ }
3159
+ this._setTransactionState({ step: "built", buildData });
3160
+ return this._signSubmitSmart(buildData);
3161
+ }
3162
+ /**
3163
+ * Steps 2–3 of the smart-wallet flow: sign the prepared auth digest with the
3164
+ * passkey, then submit. Shared by `_runSmartTx` (atomic) and `signAndSubmitTx`
3165
+ * (split flow, when a smart build is already on the state machine).
3166
+ */
3167
+ async _signSubmitSmart(buildData) {
3168
+ const address = this._session?.wallet?.address;
3169
+ const smart = buildData.smart;
3170
+ if (!address || !smart) {
3171
+ const details = "no prepared smart transaction";
3172
+ this._setTransactionState({ step: "error", phase: "signing", buildData, details });
3173
+ return { status: "error", buildData, details };
3174
+ }
3175
+ if (!this._passkeySign) {
3176
+ const details = "Passkey signer not configured";
3177
+ this._setTransactionState({ step: "error", phase: "signing", buildData, details });
3178
+ return { status: "error", buildData, details };
3179
+ }
3180
+ this._setTransactionState({ step: "signing", buildData });
3181
+ let assertion;
3182
+ try {
3183
+ assertion = await this._passkeySign({ credentialId: smart.credentialId, challenge: smart.digest });
3184
+ } catch (err) {
3185
+ const details = err instanceof Error ? err.message : void 0;
3186
+ this._setTransactionState({ step: "error", phase: "signing", buildData, ...details && { details } });
3187
+ return { status: "error", buildData, ...details && { details } };
3188
+ }
3189
+ this._setTransactionState({ step: "submitting", buildData });
3190
+ const outcomeExtra = { buildData };
3191
+ try {
3192
+ const { data, error } = await this._api.POST("/tx/submit", {
3193
+ body: {
3194
+ network: this.getNetwork(),
3195
+ address,
3196
+ smart: { entryXdr: smart.entryXdr, funcXdr: smart.funcXdr, assertion }
3197
+ }
3198
+ });
3199
+ if (!error && data?.success && data.content) {
3200
+ const { hash, status: backendStatus, resultCode } = data.content;
3201
+ if (backendStatus === "SUCCESS") {
3202
+ this._setTransactionState({ step: "success", hash, buildData });
3203
+ return { status: "success", hash, ...outcomeExtra };
3204
+ }
3205
+ if (backendStatus === "PENDING") {
3206
+ this._setTransactionState({ step: "submitted", hash, buildData });
3207
+ return { status: "pending", hash, ...outcomeExtra };
3208
+ }
3209
+ this._setTransactionState({
3210
+ step: "error",
3211
+ phase: "submitting",
3212
+ buildData,
3213
+ ...resultCode && { details: resultCode }
3214
+ });
3215
+ return { status: "error", hash, ...outcomeExtra, ...resultCode && { details: resultCode, resultCode } };
3216
+ }
3217
+ const details = error?.details;
3218
+ this._setTransactionState({ step: "error", phase: "submitting", buildData, ...details && { details } });
3219
+ return { status: "error", ...outcomeExtra, ...details && { details } };
3220
+ } catch (err) {
3221
+ const details = err instanceof Error ? err.message : void 0;
3222
+ this._setTransactionState({ step: "error", phase: "submitting", buildData, ...details && { details } });
3223
+ return { status: "error", ...outcomeExtra, ...details && { details } };
3224
+ }
3225
+ }
2870
3226
  // ─── App config ───────────────────────────────────────────────────────────
2871
3227
  async getAppConfig() {
2872
3228
  try {
@@ -2920,10 +3276,18 @@ var PollarClient = class {
2920
3276
  this._txHistoryState = next;
2921
3277
  for (const cb of this._txHistoryStateListeners) cb(next);
2922
3278
  }
3279
+ _setSessionsState(next) {
3280
+ this._sessionsState = next;
3281
+ for (const cb of this._sessionsStateListeners) cb(next);
3282
+ }
2923
3283
  _setWalletBalanceState(next) {
2924
3284
  this._walletBalanceState = next;
2925
3285
  for (const cb of this._walletBalanceStateListeners) cb(next);
2926
3286
  }
3287
+ _setEnabledAssetsState(next) {
3288
+ this._enabledAssetsState = next;
3289
+ for (const cb of this._enabledAssetsStateListeners) cb(next);
3290
+ }
2927
3291
  // ─── Private ──────────────────────────────────────────────────────────────
2928
3292
  _newController() {
2929
3293
  this._loginController?.abort();
@@ -2948,6 +3312,7 @@ var PollarClient = class {
2948
3312
  this._walletAdapter = adapter;
2949
3313
  await writeWalletType(this._storage, this.apiKeyHash, id);
2950
3314
  },
3315
+ ...this._passkey ? { passkey: this._passkey } : {},
2951
3316
  ...this._deviceLabel ? { deviceLabel: this._deviceLabel } : {}
2952
3317
  };
2953
3318
  }
@@ -2977,7 +3342,7 @@ var PollarClient = class {
2977
3342
  }
2978
3343
  }
2979
3344
  if (id === "freighter" /* FREIGHTER */) return new FreighterAdapter();
2980
- if (id === "albedo" /* ALBEDO */) return new AlbedoAdapter();
3345
+ if (id === "albedo" /* ALBEDO */) return new AlbedoAdapter(this.getNetwork() === "mainnet" ? "public" : "testnet");
2981
3346
  throw new Error(
2982
3347
  `[PollarClient] No wallet adapter configured for "${id}". Pass a walletAdapter resolver in PollarClientConfig.`
2983
3348
  );
@@ -3018,21 +3383,66 @@ var PollarClient = class {
3018
3383
  }
3019
3384
  }
3020
3385
  console.info("[PollarClient] Session restored from storage");
3021
- this._setAuthState({ step: "authenticated", session: this._session });
3386
+ this._setAuthState({ step: "authenticated", session: this._session, verified: false });
3022
3387
  this._scheduleNextRefresh();
3388
+ void this._resume();
3023
3389
  } else {
3024
3390
  console.info("[PollarClient] No session in storage");
3025
3391
  }
3026
3392
  }
3393
+ /**
3394
+ * Validate the restored session against the server and repopulate the
3395
+ * in-memory profile (PII is never persisted, so it's null after a cold
3396
+ * reload). Goes through the normal authed client, so it coalesces with any
3397
+ * in-flight refresh (onRequest awaits `_refreshPromise`) and, being a GET,
3398
+ * is auto-retried after a 401-triggered refresh.
3399
+ *
3400
+ * - 200 → store profile, mark the session `verified`.
3401
+ * - 401 → the refresh-on-401 path already ran; if the family was
3402
+ * revoked, refresh failed and `_clearSession()` took us to
3403
+ * idle. Nothing to do here — don't double-handle.
3404
+ * - network error → stay optimistic (do NOT log out); revalidated later on
3405
+ * `visibilitychange` or first use.
3406
+ */
3407
+ async _resume() {
3408
+ if (!this._session) return;
3409
+ this._resumeController?.abort();
3410
+ const controller = new AbortController();
3411
+ this._resumeController = controller;
3412
+ try {
3413
+ const { data, error } = await this._api.GET("/auth/session/resume", { signal: controller.signal });
3414
+ if (error || !data) return;
3415
+ const content = data.content;
3416
+ if (!content || !this._session) return;
3417
+ this._profile = { ...content };
3418
+ this._setAuthState({ step: "authenticated", session: this._session, verified: true });
3419
+ } catch (err) {
3420
+ if (err?.name === "AbortError") return;
3421
+ console.warn("[PollarClient] resume failed (network); will retry", err);
3422
+ } finally {
3423
+ if (this._resumeController === controller) this._resumeController = null;
3424
+ }
3425
+ }
3027
3426
  async _storeSession(session) {
3028
3427
  console.info("[PollarClient] Session stored");
3428
+ const w = session.wallet;
3029
3429
  const persisted = {
3030
3430
  clientSessionId: session.clientSessionId,
3031
3431
  userId: session.userId ?? null,
3032
3432
  status: session.status,
3033
3433
  token: session.token,
3034
3434
  user: session.user,
3035
- wallet: session.wallet
3435
+ // The wire response still carries the legacy `publicKey` alias (kept for
3436
+ // older SDKs); the persisted session standardizes on `address` only.
3437
+ wallet: {
3438
+ type: w.type,
3439
+ address: w.address ?? w.publicKey ?? null,
3440
+ ...w.existsOnStellar !== void 0 ? { existsOnStellar: w.existsOnStellar } : {},
3441
+ ...w.createdAt !== void 0 ? { createdAt: w.createdAt } : {},
3442
+ ...w.linkedAt !== void 0 ? { linkedAt: w.linkedAt } : {},
3443
+ ...w.network !== void 0 ? { network: w.network } : {},
3444
+ ...w.deployTxHash !== void 0 ? { deployTxHash: w.deployTxHash } : {}
3445
+ }
3036
3446
  };
3037
3447
  this._session = persisted;
3038
3448
  if (session.data) {
@@ -3045,7 +3455,7 @@ var PollarClient = class {
3045
3455
  };
3046
3456
  }
3047
3457
  await writeStorage(this._storage, this.apiKeyHash, persisted);
3048
- this._setAuthState({ step: "authenticated", session: persisted });
3458
+ this._setAuthState({ step: "authenticated", session: persisted, verified: true });
3049
3459
  this._scheduleNextRefresh();
3050
3460
  }
3051
3461
  async _clearSession() {
@@ -3128,6 +3538,6 @@ var StellarClient = class {
3128
3538
  // src/index.ts
3129
3539
  _setDefaultKeyManagerFactory((_storage, apiKey) => new WebCryptoKeyManager(apiKey));
3130
3540
 
3131
- export { AUTH_ERROR_CODES, AlbedoAdapter, FreighterAdapter, PollarClient, StellarClient, WalletType, WebCryptoKeyManager, buildProof, canonicalEcJwk, claimDistributionRule, computeJwkThumbprint, createLocalStorageAdapter, createMemoryAdapter, createOffRamp, createOnRamp, defaultKeyManager, defaultStorage, getKycProviders, getKycStatus, getRampTransaction, getRampsQuote, isValidSession, listDistributionRules, normalizeHtu, pollKycStatus, pollRampTransaction, resolveKyc, startKyc };
3541
+ export { AUTH_ERROR_CODES, AlbedoAdapter, FreighterAdapter, POLLAR_CORE_VERSION, PollarClient, StellarClient, WalletType, WebCryptoKeyManager, buildProof, canonicalEcJwk, claimDistributionRule, computeJwkThumbprint, createLocalStorageAdapter, createMemoryAdapter, createOffRamp, createOnRamp, defaultKeyManager, defaultStorage, getKycProviders, getKycStatus, getRampTransaction, getRampsQuote, isValidSession, listDistributionRules, normalizeHtu, pollKycStatus, pollRampTransaction, resolveKyc, startKyc };
3132
3542
  //# sourceMappingURL=index.mjs.map
3133
3543
  //# sourceMappingURL=index.mjs.map