@pollar/core 0.9.0-rc.0 → 0.9.0-rc.2

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.rn.mjs CHANGED
@@ -302,7 +302,6 @@ var NobleKeyManager = class {
302
302
  if (this.privateKey) return;
303
303
  if (!this._initPromise) {
304
304
  this._initPromise = this._doInit().catch((err) => {
305
- console.error("[PollarClient:keys] NobleKeyManager init failed", err);
306
305
  this._initPromise = null;
307
306
  throw err;
308
307
  });
@@ -1010,6 +1009,16 @@ function normalizeHtu(rawUrl) {
1010
1009
  return `${scheme}//${host}${portPart}${url.pathname}`;
1011
1010
  }
1012
1011
 
1012
+ // src/lib/logger.ts
1013
+ var RANK = { silent: 0, error: 1, warn: 2, info: 3, debug: 4 };
1014
+ function createLogger(level = "info", sink = console) {
1015
+ const threshold = RANK[level];
1016
+ const gate = (lvl) => (...args) => {
1017
+ if (threshold >= RANK[lvl]) sink[lvl](...args);
1018
+ };
1019
+ return { error: gate("error"), warn: gate("warn"), info: gate("info"), debug: gate("debug") };
1020
+ }
1021
+
1013
1022
  // src/storage/web.ts
1014
1023
  var LOG_PREFIX = "[PollarClient:storage]";
1015
1024
  function createMemoryAdapter() {
@@ -1033,7 +1042,7 @@ function createLocalStorageAdapter(options = {}) {
1033
1042
  function degrade(reason, error) {
1034
1043
  if (degraded) return;
1035
1044
  degraded = true;
1036
- console.warn(`${LOG_PREFIX} localStorage unavailable (${reason}); degrading to in-memory storage`);
1045
+ (options.logger ?? console).warn(`${LOG_PREFIX} localStorage unavailable (${reason}); degrading to in-memory storage`);
1037
1046
  options.onDegrade?.(reason, error);
1038
1047
  }
1039
1048
  return {
@@ -1098,7 +1107,7 @@ function defaultStorage(options = {}) {
1098
1107
  }
1099
1108
 
1100
1109
  // src/version.ts
1101
- var POLLAR_CORE_VERSION = "0.9.0-rc.0" ;
1110
+ var POLLAR_CORE_VERSION = "0.9.0-rc.2" ;
1102
1111
 
1103
1112
  // src/visibility/noop.ts
1104
1113
  function createNoopVisibilityProvider() {
@@ -1270,7 +1279,10 @@ function openAlbedoPopup(url) {
1270
1279
  }
1271
1280
  function waitForAlbedoPopup() {
1272
1281
  return new Promise((resolve, reject) => {
1273
- const timeout = setTimeout(() => reject(new Error("Albedo response timeout")), 2 * 60 * 1e3);
1282
+ const timeout = setTimeout(() => {
1283
+ window.removeEventListener("message", handler);
1284
+ reject(new Error("Albedo response timeout"));
1285
+ }, 2 * 60 * 1e3);
1274
1286
  function handler(event) {
1275
1287
  if (event.origin !== window.location.origin || event.data?.type !== "ALBEDO_RESULT") return;
1276
1288
  clearTimeout(timeout);
@@ -1280,24 +1292,6 @@ function waitForAlbedoPopup() {
1280
1292
  window.addEventListener("message", handler);
1281
1293
  });
1282
1294
  }
1283
- function waitForAlbedoResult() {
1284
- return new Promise((resolve, reject) => {
1285
- const timeout = setTimeout(() => reject(new Error("Albedo response timeout")), 2 * 60 * 1e3);
1286
- const parseResult = () => {
1287
- const params = new URLSearchParams(window.location.search);
1288
- if (!params.has("pubkey") && !params.has("signed_envelope_xdr") && !params.has("signed_xdr")) return;
1289
- clearTimeout(timeout);
1290
- const result = {};
1291
- params.forEach((value, key) => {
1292
- result[key] = value;
1293
- });
1294
- window.history.replaceState({}, document.title, window.location.pathname);
1295
- resolve(result);
1296
- };
1297
- parseResult();
1298
- window.addEventListener("popstate", parseResult);
1299
- });
1300
- }
1301
1295
  var AlbedoAdapter = class {
1302
1296
  /**
1303
1297
  * Network used for `connect` and `signAuthEntry` (which carry no per-call
@@ -1339,10 +1333,10 @@ var AlbedoAdapter = class {
1339
1333
  url.searchParams.set("xdr", xdr);
1340
1334
  url.searchParams.set("app_name", "Pollar");
1341
1335
  url.searchParams.set("network", albedoNetwork(options, this.network));
1342
- url.searchParams.set("callback", window.location.href);
1336
+ url.searchParams.set("callback", `${window.location.origin}/albedo-callback`);
1343
1337
  url.searchParams.set("origin", window.location.origin);
1344
- window.location.href = url.toString();
1345
- const result = await waitForAlbedoResult();
1338
+ openAlbedoPopup(url.toString());
1339
+ const result = await waitForAlbedoPopup();
1346
1340
  if (!result.signed_envelope_xdr) throw new Error("Albedo signing rejected");
1347
1341
  return { signedTxXdr: result.signed_envelope_xdr };
1348
1342
  }
@@ -1352,10 +1346,10 @@ var AlbedoAdapter = class {
1352
1346
  url.searchParams.set("xdr", entryXdr);
1353
1347
  url.searchParams.set("app_name", "Pollar");
1354
1348
  url.searchParams.set("network", this.network);
1355
- url.searchParams.set("callback", window.location.href);
1349
+ url.searchParams.set("callback", `${window.location.origin}/albedo-callback`);
1356
1350
  url.searchParams.set("origin", window.location.origin);
1357
- window.location.href = url.toString();
1358
- const result = await waitForAlbedoResult();
1351
+ openAlbedoPopup(url.toString());
1352
+ const result = await waitForAlbedoPopup();
1359
1353
  if (!result.signed_xdr) throw new Error("Albedo auth entry signing rejected");
1360
1354
  return { signedAuthEntry: result.signed_xdr };
1361
1355
  }
@@ -1382,85 +1376,85 @@ function isBoundedString(v, max, allowEmpty = false) {
1382
1376
  if (!allowEmpty && v.length === 0) return false;
1383
1377
  return v.length <= max;
1384
1378
  }
1385
- function isValidSession(value) {
1379
+ function isValidSession(value, logger = console) {
1386
1380
  if (typeof value !== "object" || value === null) {
1387
- console.warn("[PollarClient:session] Invalid session \u2014 value is not an object");
1381
+ logger.debug("[PollarClient:session] Invalid session \u2014 value is not an object");
1388
1382
  return false;
1389
1383
  }
1390
1384
  const s = value;
1391
1385
  if (!isBoundedString(s["clientSessionId"], MAX_CLIENT_SESSION_ID)) {
1392
- console.warn("[PollarClient:session] Invalid session \u2014 clientSessionId missing/empty/too long");
1386
+ logger.debug("[PollarClient:session] Invalid session \u2014 clientSessionId missing/empty/too long");
1393
1387
  return false;
1394
1388
  }
1395
1389
  if (s["userId"] !== null && !isBoundedString(s["userId"], MAX_USER_ID)) {
1396
- console.warn("[PollarClient:session] Invalid session \u2014 userId must be string|null");
1390
+ logger.debug("[PollarClient:session] Invalid session \u2014 userId must be string|null");
1397
1391
  return false;
1398
1392
  }
1399
1393
  if (!isBoundedString(s["status"], MAX_STATUS)) {
1400
- console.warn("[PollarClient:session] Invalid session \u2014 status must be string");
1394
+ logger.debug("[PollarClient:session] Invalid session \u2014 status must be string");
1401
1395
  return false;
1402
1396
  }
1403
1397
  const token = s["token"];
1404
1398
  if (typeof token !== "object" || token === null) {
1405
- console.warn("[PollarClient:session] Invalid session \u2014 token missing or not an object");
1399
+ logger.debug("[PollarClient:session] Invalid session \u2014 token missing or not an object");
1406
1400
  return false;
1407
1401
  }
1408
1402
  const t = token;
1409
1403
  if (!isBoundedString(t["accessToken"], MAX_ACCESS_TOKEN)) {
1410
- console.warn("[PollarClient:session] Invalid session \u2014 token.accessToken missing/empty/too long");
1404
+ logger.debug("[PollarClient:session] Invalid session \u2014 token.accessToken missing/empty/too long");
1411
1405
  return false;
1412
1406
  }
1413
1407
  if (!isBoundedString(t["refreshToken"], MAX_REFRESH_TOKEN)) {
1414
- console.warn("[PollarClient:session] Invalid session \u2014 token.refreshToken missing/empty/too long");
1408
+ logger.debug("[PollarClient:session] Invalid session \u2014 token.refreshToken missing/empty/too long");
1415
1409
  return false;
1416
1410
  }
1417
1411
  if (typeof t["expiresAt"] !== "number" || !Number.isFinite(t["expiresAt"])) {
1418
- console.warn("[PollarClient:session] Invalid session \u2014 token.expiresAt must be a finite number");
1412
+ logger.debug("[PollarClient:session] Invalid session \u2014 token.expiresAt must be a finite number");
1419
1413
  return false;
1420
1414
  }
1421
1415
  const user = s["user"];
1422
1416
  if (typeof user !== "object" || user === null) {
1423
- console.warn("[PollarClient:session] Invalid session \u2014 user missing or not an object");
1417
+ logger.debug("[PollarClient:session] Invalid session \u2014 user missing or not an object");
1424
1418
  return false;
1425
1419
  }
1426
1420
  const u = user;
1427
1421
  if (u["id"] !== void 0 && !isBoundedString(u["id"], MAX_USER_ID)) {
1428
- console.warn("[PollarClient:session] Invalid session \u2014 user.id must be string if present");
1422
+ logger.debug("[PollarClient:session] Invalid session \u2014 user.id must be string if present");
1429
1423
  return false;
1430
1424
  }
1431
1425
  if (typeof u["ready"] !== "boolean") {
1432
- console.warn("[PollarClient:session] Invalid session \u2014 user.ready must be boolean");
1426
+ logger.debug("[PollarClient:session] Invalid session \u2014 user.ready must be boolean");
1433
1427
  return false;
1434
1428
  }
1435
1429
  const wallet = s["wallet"];
1436
1430
  if (typeof wallet !== "object" || wallet === null) {
1437
- console.warn("[PollarClient:session] Invalid session \u2014 wallet missing or not an object");
1431
+ logger.debug("[PollarClient:session] Invalid session \u2014 wallet missing or not an object");
1438
1432
  return false;
1439
1433
  }
1440
1434
  const w = wallet;
1441
- if (w["type"] !== "custodial" && w["type"] !== "smart" && w["type"] !== "external") {
1442
- console.warn("[PollarClient:session] Invalid session \u2014 wallet.type must be custodial|smart|external");
1435
+ if (w["type"] !== "internal" && w["type"] !== "smart" && w["type"] !== "external") {
1436
+ logger.debug("[PollarClient:session] Invalid session \u2014 wallet.type must be internal|smart|external");
1443
1437
  return false;
1444
1438
  }
1445
1439
  if (w["address"] !== null && !isBoundedString(w["address"], MAX_WALLET_PUBLIC_KEY)) {
1446
- console.warn("[PollarClient:session] Invalid session \u2014 wallet.address must be string|null");
1440
+ logger.debug("[PollarClient:session] Invalid session \u2014 wallet.address must be string|null");
1447
1441
  return false;
1448
1442
  }
1449
1443
  if (w["existsOnStellar"] !== void 0 && typeof w["existsOnStellar"] !== "boolean") {
1450
- console.warn("[PollarClient:session] Invalid session \u2014 wallet.existsOnStellar must be boolean if present");
1444
+ logger.debug("[PollarClient:session] Invalid session \u2014 wallet.existsOnStellar must be boolean if present");
1451
1445
  return false;
1452
1446
  }
1453
1447
  if (w["createdAt"] !== void 0 && (typeof w["createdAt"] !== "number" || !Number.isFinite(w["createdAt"]))) {
1454
- console.warn("[PollarClient:session] Invalid session \u2014 wallet.createdAt must be a finite number if present");
1448
+ logger.debug("[PollarClient:session] Invalid session \u2014 wallet.createdAt must be a finite number if present");
1455
1449
  return false;
1456
1450
  }
1457
1451
  if (w["linkedAt"] !== void 0 && (typeof w["linkedAt"] !== "number" || !Number.isFinite(w["linkedAt"]))) {
1458
- console.warn("[PollarClient:session] Invalid session \u2014 wallet.linkedAt must be a finite number if present");
1452
+ logger.debug("[PollarClient:session] Invalid session \u2014 wallet.linkedAt must be a finite number if present");
1459
1453
  return false;
1460
1454
  }
1461
1455
  return true;
1462
1456
  }
1463
- async function readStorage(storage, apiKeyHash) {
1457
+ async function readStorage(storage, apiKeyHash, logger = console) {
1464
1458
  const raw = await storage.get(sessionStorageKey(apiKeyHash));
1465
1459
  if (!raw) return null;
1466
1460
  try {
@@ -1470,10 +1464,13 @@ async function readStorage(storage, apiKeyHash) {
1470
1464
  if (w && w["address"] == null && typeof w["publicKey"] === "string") {
1471
1465
  w["address"] = w["publicKey"];
1472
1466
  }
1467
+ if (w && w["type"] === "custodial") {
1468
+ w["type"] = "internal";
1469
+ }
1473
1470
  }
1474
- if (!isValidSession(session)) {
1471
+ if (!isValidSession(session, logger)) {
1475
1472
  await storage.remove(sessionStorageKey(apiKeyHash));
1476
- console.warn("[PollarClient:session] Stored session is invalid \u2014 clearing storage");
1473
+ logger.warn("[PollarClient:session] Stored session is invalid \u2014 clearing storage");
1477
1474
  return null;
1478
1475
  }
1479
1476
  if (session.token.expiresAt * 1e3 < Date.now()) {
@@ -1481,7 +1478,7 @@ async function readStorage(storage, apiKeyHash) {
1481
1478
  }
1482
1479
  return session;
1483
1480
  } catch (error) {
1484
- console.error("[PollarClient:session] Failed to parse session from storage", error);
1481
+ logger.error("[PollarClient:session] Failed to parse session from storage", error);
1485
1482
  await storage.remove(sessionStorageKey(apiKeyHash));
1486
1483
  return null;
1487
1484
  }
@@ -1543,7 +1540,7 @@ function abortableDelay(ms, signal) {
1543
1540
  });
1544
1541
  }
1545
1542
  var MAX_BACKOFF_MS = 5e3;
1546
- async function streamUntilFound(api, clientSessionId, check, retryDelayMs = 200, signal) {
1543
+ async function streamUntilFound(api, clientSessionId, check, retryDelayMs = 200, signal, logger = console) {
1547
1544
  let backoff = retryDelayMs;
1548
1545
  const sleep = async (ms) => {
1549
1546
  if (ms <= 0) return;
@@ -1561,7 +1558,7 @@ async function streamUntilFound(api, clientSessionId, check, retryDelayMs = 200,
1561
1558
  }));
1562
1559
  } catch (e) {
1563
1560
  if (e instanceof Error && e.name === "AbortError") throw e;
1564
- console.warn("[PollarClient:stream] session-status request failed; will retry", e);
1561
+ logger.debug("[PollarClient:stream] session-status request failed; will retry", e);
1565
1562
  }
1566
1563
  if (error || !data) {
1567
1564
  await sleep(backoff);
@@ -1570,16 +1567,12 @@ async function streamUntilFound(api, clientSessionId, check, retryDelayMs = 200,
1570
1567
  }
1571
1568
  const reader = data.getReader();
1572
1569
  const decoder = new TextDecoder();
1573
- let streamDone = false;
1574
1570
  let sawAnyChunk = false;
1575
1571
  try {
1576
1572
  while (true) {
1577
1573
  throwIfAborted(signal);
1578
1574
  const { done, value } = await reader.read();
1579
- if (done) {
1580
- streamDone = true;
1581
- break;
1582
- }
1575
+ if (done) break;
1583
1576
  sawAnyChunk = true;
1584
1577
  const chunk = decoder.decode(value);
1585
1578
  for (const message of chunk.split("\n\n").filter(Boolean)) {
@@ -1601,17 +1594,16 @@ async function streamUntilFound(api, clientSessionId, check, retryDelayMs = 200,
1601
1594
  } catch (e) {
1602
1595
  if (e instanceof Error && e.name === "AbortError") throw e;
1603
1596
  if (e instanceof SessionStatusError) throw e;
1604
- console.warn("[PollarClient:stream] session-status stream read failed; will retry", e);
1597
+ logger.debug("[PollarClient:stream] session-status stream read failed; will retry", e);
1605
1598
  } finally {
1606
1599
  reader.releaseLock();
1607
1600
  }
1608
1601
  if (sawAnyChunk) backoff = retryDelayMs;
1609
1602
  else backoff = Math.min(backoff * 2, MAX_BACKOFF_MS);
1610
- const delay = streamDone ? backoff : 0;
1611
- if (delay) await sleep(delay);
1603
+ await sleep(backoff);
1612
1604
  }
1613
1605
  }
1614
- async function pollUntilFound(baseUrl, clientSessionId, check, intervalMs = 500, signal) {
1606
+ async function pollUntilFound(baseUrl, clientSessionId, check, intervalMs = 500, signal, logger = console) {
1615
1607
  const url = `${baseUrl}/auth/session/status/${encodeURIComponent(clientSessionId)}/poll`;
1616
1608
  let backoff = intervalMs;
1617
1609
  const sleep = async (ms) => {
@@ -1629,7 +1621,7 @@ async function pollUntilFound(baseUrl, clientSessionId, check, intervalMs = 500,
1629
1621
  envelope = await response.json().catch(() => null);
1630
1622
  } catch (e) {
1631
1623
  if (e instanceof Error && e.name === "AbortError") throw e;
1632
- console.warn("[PollarClient:stream] session-status poll failed; will retry", e);
1624
+ logger.debug("[PollarClient:stream] session-status poll failed; will retry", e);
1633
1625
  }
1634
1626
  if (httpStatus === 404 || envelope?.code === "INVALID_CLIENT_SESSION_ID") {
1635
1627
  throw new SessionStatusError("INVALID_CLIENT_SESSION_ID");
@@ -1646,13 +1638,13 @@ async function pollUntilFound(baseUrl, clientSessionId, check, intervalMs = 500,
1646
1638
  }
1647
1639
  }
1648
1640
  function waitForSessionReady(args) {
1649
- const { api, baseUrl, clientSessionId, check, useStreaming, retryDelayMs, signal } = args;
1650
- return useStreaming ? streamUntilFound(api, clientSessionId, check, retryDelayMs ?? 200, signal) : pollUntilFound(baseUrl, clientSessionId, check, retryDelayMs ?? 500, signal);
1641
+ const { api, baseUrl, clientSessionId, check, useStreaming, retryDelayMs, signal, logger = console } = args;
1642
+ return useStreaming ? streamUntilFound(api, clientSessionId, check, retryDelayMs ?? 200, signal, logger) : pollUntilFound(baseUrl, clientSessionId, check, retryDelayMs ?? 500, signal, logger);
1651
1643
  }
1652
1644
 
1653
1645
  // src/client/auth/authenticate.ts
1654
1646
  async function authenticate(clientSessionId, deps, expectedWallet) {
1655
- const { api, basePath, useStreaming, signal, setAuthState, storeSession, clearSession } = deps;
1647
+ const { api, logger, basePath, useStreaming, signal, setAuthState, storeSession, clearSession } = deps;
1656
1648
  setAuthState({ step: "authenticating" });
1657
1649
  try {
1658
1650
  await waitForSessionReady({
@@ -1661,7 +1653,8 @@ async function authenticate(clientSessionId, deps, expectedWallet) {
1661
1653
  clientSessionId,
1662
1654
  check: (data2) => data2?.status === "READY",
1663
1655
  useStreaming,
1664
- signal
1656
+ signal,
1657
+ logger
1665
1658
  });
1666
1659
  } catch (err) {
1667
1660
  if (err instanceof SessionStatusError) {
@@ -1686,18 +1679,19 @@ async function authenticate(clientSessionId, deps, expectedWallet) {
1686
1679
  },
1687
1680
  signal
1688
1681
  });
1689
- if (data?.code === "SDK_LOGIN_SUCCESS" && isValidSession(data?.content)) {
1690
- if (expectedWallet && data.content.data.providers.wallet?.address !== expectedWallet) {
1682
+ if (data?.code === "SDK_LOGIN_SUCCESS" && isValidSession(data?.content, logger)) {
1683
+ const sessionWallet = data.content.data?.providers?.wallet?.address;
1684
+ if (expectedWallet && sessionWallet !== expectedWallet) {
1691
1685
  setAuthState({
1692
1686
  step: "error",
1693
1687
  previousStep: "authenticating",
1694
1688
  message: "Wallet mismatch: session wallet does not match connected wallet",
1695
1689
  errorCode: AUTH_ERROR_CODES.WALLET_AUTH_FAILED
1696
1690
  });
1697
- clearSession();
1691
+ await clearSession();
1698
1692
  return;
1699
1693
  }
1700
- storeSession(data.content);
1694
+ await storeSession(data.content);
1701
1695
  } else {
1702
1696
  setAuthState({
1703
1697
  step: "error",
@@ -1705,7 +1699,7 @@ async function authenticate(clientSessionId, deps, expectedWallet) {
1705
1699
  message: "Failed to load session",
1706
1700
  errorCode: AUTH_ERROR_CODES.AUTH_FAILED
1707
1701
  });
1708
- clearSession();
1702
+ await clearSession();
1709
1703
  }
1710
1704
  }
1711
1705
 
@@ -2004,7 +1998,9 @@ var PollarClient = class {
2004
1998
  this.apiKey = config.apiKey;
2005
1999
  this.id = randomUUID();
2006
2000
  this.basePath = `${config.baseUrl || "https://sdk.api.pollar.xyz"}/v1`;
2001
+ this._log = createLogger(config.logLevel ?? "info", config.logger);
2007
2002
  this._storage = config.storage ?? defaultStorage({
2003
+ logger: this._log,
2008
2004
  onDegrade: (reason, error) => {
2009
2005
  config.onStorageDegrade?.(reason, error);
2010
2006
  this._dispatchStorageDegrade(reason, error);
@@ -2019,7 +2015,7 @@ var PollarClient = class {
2019
2015
  this._visibilityProvider = config.visibilityProvider ?? defaultVisibilityProvider();
2020
2016
  this._maxIdleMs = config.maxIdleMs;
2021
2017
  this._openAuthUrl = config.openAuthUrl ?? defaultWebOAuthOpener;
2022
- this._oauthRedirectUri = config.oauthRedirectUri ?? (isBrowser ? window.location.origin : "");
2018
+ this._oauthRedirectUri = config.oauthRedirectUri ?? (isBrowser ? window.location?.origin ?? "" : "");
2023
2019
  this._api = createApiClient(this.basePath);
2024
2020
  this._wireMiddlewares();
2025
2021
  this._networkState = { step: "connected", network: config.stellarNetwork ?? "testnet" };
@@ -2028,7 +2024,7 @@ var PollarClient = class {
2028
2024
  this._initialized = Promise.resolve();
2029
2025
  return;
2030
2026
  }
2031
- console.info(
2027
+ this._log.info(
2032
2028
  `[PollarClient] Initialized v${POLLAR_CORE_VERSION} \u2014 endpoint: ${this.basePath}, network: ${this._networkState.network}`
2033
2029
  );
2034
2030
  this._initialized = this._initialize();
@@ -2055,7 +2051,7 @@ var PollarClient = class {
2055
2051
  const sessionKey = sessionStorageKey(this._apiKeyHash);
2056
2052
  const handler = (e) => {
2057
2053
  if (e.key === sessionKey) {
2058
- this._restoreSession().catch((err) => console.error("[PollarClient] Cross-tab restore failed", err));
2054
+ this._restoreSession().catch((err) => this._log.error("[PollarClient] Cross-tab restore failed", err));
2059
2055
  }
2060
2056
  };
2061
2057
  window.addEventListener("storage", handler);
@@ -2064,7 +2060,7 @@ var PollarClient = class {
2064
2060
  try {
2065
2061
  await this._keyManager.init();
2066
2062
  } catch (err) {
2067
- console.warn("[PollarClient] KeyManager init failed; DPoP unavailable for this session", err);
2063
+ this._log.warn("[PollarClient] KeyManager init failed; DPoP unavailable for this session", err);
2068
2064
  }
2069
2065
  await this._restoreSession();
2070
2066
  this._visibilityUnsubscribe = this._visibilityProvider.onChange((visible) => {
@@ -2105,7 +2101,7 @@ var PollarClient = class {
2105
2101
  try {
2106
2102
  self._requestBodyCache.set(request, await request.clone().arrayBuffer());
2107
2103
  } catch (err) {
2108
- console.warn("[PollarClient] Could not snapshot request body for retry", err);
2104
+ this._log.warn("[PollarClient] Could not snapshot request body for retry", err);
2109
2105
  }
2110
2106
  }
2111
2107
  const isRefresh = request.url.includes("/auth/refresh");
@@ -2164,7 +2160,7 @@ var PollarClient = class {
2164
2160
  this._keyManager
2165
2161
  );
2166
2162
  } catch (err) {
2167
- console.warn("[PollarClient] DPoP proof build failed", err);
2163
+ this._log.warn("[PollarClient] DPoP proof build failed", err);
2168
2164
  return null;
2169
2165
  }
2170
2166
  }
@@ -2218,7 +2214,7 @@ var PollarClient = class {
2218
2214
  async _doRefresh() {
2219
2215
  const refreshToken = this._session?.token?.refreshToken;
2220
2216
  if (!refreshToken) {
2221
- console.warn("[PollarClient] Refresh skipped: no refresh token in session");
2217
+ this._log.warn("[PollarClient] Refresh skipped: no refresh token in session");
2222
2218
  await this._clearSession();
2223
2219
  throw new Error("No refresh token available");
2224
2220
  }
@@ -2229,18 +2225,18 @@ var PollarClient = class {
2229
2225
  data = response.data;
2230
2226
  error = response.error;
2231
2227
  } catch (err) {
2232
- console.error("[PollarClient] /auth/refresh request threw", err);
2228
+ this._log.error("[PollarClient] /auth/refresh request threw", err);
2233
2229
  await this._clearSession();
2234
2230
  throw err;
2235
2231
  }
2236
2232
  if (error || !data) {
2237
- console.error("[PollarClient] /auth/refresh returned error", { error });
2233
+ this._log.error("[PollarClient] /auth/refresh returned error", { error });
2238
2234
  await this._clearSession();
2239
2235
  throw new Error("Refresh failed");
2240
2236
  }
2241
2237
  const successData = data;
2242
2238
  if (!successData.success || !successData.content?.token) {
2243
- console.error("[PollarClient] /auth/refresh response malformed", {
2239
+ this._log.error("[PollarClient] /auth/refresh response malformed", {
2244
2240
  success: successData.success,
2245
2241
  hasToken: !!successData.content?.token
2246
2242
  });
@@ -2249,7 +2245,7 @@ var PollarClient = class {
2249
2245
  }
2250
2246
  const newToken = successData.content.token;
2251
2247
  if (typeof newToken.accessToken !== "string" || typeof newToken.refreshToken !== "string" || typeof newToken.expiresAt !== "number") {
2252
- console.error("[PollarClient] /auth/refresh token shape invalid", {
2248
+ this._log.error("[PollarClient] /auth/refresh token shape invalid", {
2253
2249
  accessToken: typeof newToken.accessToken,
2254
2250
  refreshToken: typeof newToken.refreshToken,
2255
2251
  expiresAt: typeof newToken.expiresAt
@@ -2261,9 +2257,9 @@ var PollarClient = class {
2261
2257
  try {
2262
2258
  this._session = { ...this._session, token: newToken };
2263
2259
  await writeStorage(this._storage, this.apiKeyHash, this._session);
2264
- console.info("[PollarClient] Tokens refreshed");
2260
+ this._log.info("[PollarClient] Tokens refreshed");
2265
2261
  } catch (err) {
2266
- console.error("[PollarClient] Failed to persist refreshed session", err);
2262
+ this._log.error("[PollarClient] Failed to persist refreshed session", err);
2267
2263
  }
2268
2264
  this._scheduleNextRefresh();
2269
2265
  }
@@ -2317,7 +2313,7 @@ var PollarClient = class {
2317
2313
  try {
2318
2314
  await this.refresh();
2319
2315
  } catch (err) {
2320
- console.warn("[PollarClient] Proactive refresh failed; session cleared", err);
2316
+ this._log.warn("[PollarClient] Proactive refresh failed; session cleared", err);
2321
2317
  }
2322
2318
  }
2323
2319
  _clearRefreshTimer() {
@@ -2363,7 +2359,7 @@ var PollarClient = class {
2363
2359
  try {
2364
2360
  cb(reason, error);
2365
2361
  } catch (err) {
2366
- console.error("[PollarClient] onStorageDegrade listener threw", err);
2362
+ this._log.error("[PollarClient] onStorageDegrade listener threw", err);
2367
2363
  }
2368
2364
  }
2369
2365
  }
@@ -2483,20 +2479,20 @@ var PollarClient = class {
2483
2479
  warnServerSide("logout");
2484
2480
  return;
2485
2481
  }
2486
- console.info("[PollarClient] Logout requested", { everywhere: !!options.everywhere });
2482
+ this._log.info("[PollarClient] Logout requested", { everywhere: !!options.everywhere });
2487
2483
  if (this._session?.token?.accessToken) {
2488
2484
  try {
2489
2485
  await this._api.POST("/auth/logout", {
2490
2486
  body: options.everywhere ? { everywhere: true } : {}
2491
2487
  });
2492
2488
  } catch (err) {
2493
- console.warn("[PollarClient] Server logout failed (continuing with local clear)", err);
2489
+ this._log.warn("[PollarClient] Server logout failed (continuing with local clear)", err);
2494
2490
  }
2495
2491
  }
2496
2492
  try {
2497
2493
  await this._clearSession();
2498
2494
  } catch (err) {
2499
- console.warn("[PollarClient] Local logout cleanup failed", err);
2495
+ this._log.warn("[PollarClient] Local logout cleanup failed", err);
2500
2496
  }
2501
2497
  }
2502
2498
  /** Convenience: revoke every active session for this user (all devices). */
@@ -2572,6 +2568,14 @@ var PollarClient = class {
2572
2568
  getNetworkState() {
2573
2569
  return this._networkState;
2574
2570
  }
2571
+ /**
2572
+ * The client's level-gated logger (built from `logLevel` / `logger`). Exposed
2573
+ * so the runtime layer (`@pollar/react`) can route its own logs through the
2574
+ * same level and sink instead of calling `console` directly.
2575
+ */
2576
+ getLogger() {
2577
+ return this._log;
2578
+ }
2575
2579
  setNetwork(network) {
2576
2580
  this._setNetworkState({ step: "connected", network });
2577
2581
  }
@@ -2720,7 +2724,7 @@ var PollarClient = class {
2720
2724
  this._setTransactionState({ step: "error", phase: "building", ...details && { details } });
2721
2725
  return { status: "error", ...details && { details } };
2722
2726
  } catch (err) {
2723
- console.error("[PollarClient] buildTx failed", err);
2727
+ this._log.error("[PollarClient] buildTx failed", err);
2724
2728
  this._setTransactionState({ step: "error", phase: "building" });
2725
2729
  return { status: "error" };
2726
2730
  }
@@ -3233,6 +3237,7 @@ var PollarClient = class {
3233
3237
  _flowDeps(signal) {
3234
3238
  return {
3235
3239
  api: this._api,
3240
+ logger: this._log,
3236
3241
  basePath: this.basePath,
3237
3242
  // SSE status streaming works on web; React Native's `fetch` has no
3238
3243
  // readable `response.body`, so those clients poll the non-streaming
@@ -3285,12 +3290,12 @@ var PollarClient = class {
3285
3290
  }
3286
3291
  _handleFlowError(error) {
3287
3292
  if (error instanceof Error && error.name === "AbortError") {
3288
- console.info("[PollarClient] Login cancelled");
3293
+ this._log.debug("[PollarClient] Login cancelled");
3289
3294
  this._setAuthState({ step: "idle" });
3290
3295
  return;
3291
3296
  }
3292
3297
  if (error instanceof Error && error.code === AUTH_ERROR_CODES.WALLET_RESOLVER_TIMEOUT) {
3293
- console.error("[PollarClient]", error.message);
3298
+ this._log.error("[PollarClient]", error.message);
3294
3299
  this._setAuthState({
3295
3300
  step: "error",
3296
3301
  previousStep: this._authState.step,
@@ -3299,7 +3304,7 @@ var PollarClient = class {
3299
3304
  });
3300
3305
  return;
3301
3306
  }
3302
- console.error("[PollarClient] Unexpected error in auth flow", error);
3307
+ this._log.error("[PollarClient] Unexpected error in auth flow", error);
3303
3308
  this._setAuthState({
3304
3309
  step: "error",
3305
3310
  previousStep: this._authState.step,
@@ -3308,22 +3313,25 @@ var PollarClient = class {
3308
3313
  });
3309
3314
  }
3310
3315
  async _restoreSession() {
3311
- this._session = await readStorage(this._storage, this.apiKeyHash);
3316
+ this._session = await readStorage(this._storage, this.apiKeyHash, this._log);
3312
3317
  if (this._session) {
3313
3318
  const storedType = await readWalletType(this._storage, this.apiKeyHash);
3314
3319
  if (storedType) {
3315
3320
  try {
3316
3321
  this._walletAdapter = await this._resolveWalletAdapter(storedType);
3317
3322
  } catch (err) {
3318
- console.warn("[PollarClient] Could not restore wallet adapter for stored id", { id: storedType, err });
3323
+ this._log.warn("[PollarClient] Could not restore wallet adapter for stored id", { id: storedType, err });
3319
3324
  }
3320
3325
  }
3321
- console.info("[PollarClient] Session restored from storage");
3326
+ this._log.info("[PollarClient] Session restored from storage");
3322
3327
  this._setAuthState({ step: "authenticated", session: this._session, verified: false });
3323
3328
  this._scheduleNextRefresh();
3324
3329
  void this._resume();
3325
3330
  } else {
3326
- console.info("[PollarClient] No session in storage");
3331
+ this._log.info("[PollarClient] No session in storage");
3332
+ if (this._authState.step !== "idle") {
3333
+ await this._clearSession();
3334
+ }
3327
3335
  }
3328
3336
  }
3329
3337
  /**
@@ -3354,13 +3362,13 @@ var PollarClient = class {
3354
3362
  this._setAuthState({ step: "authenticated", session: this._session, verified: true });
3355
3363
  } catch (err) {
3356
3364
  if (err?.name === "AbortError") return;
3357
- console.warn("[PollarClient] resume failed (network); will retry", err);
3365
+ this._log.warn("[PollarClient] resume failed (network); will retry", err);
3358
3366
  } finally {
3359
3367
  if (this._resumeController === controller) this._resumeController = null;
3360
3368
  }
3361
3369
  }
3362
3370
  async _storeSession(session) {
3363
- console.info("[PollarClient] Session stored");
3371
+ this._log.info("[PollarClient] Session stored");
3364
3372
  const w = session.wallet;
3365
3373
  const persisted = {
3366
3374
  clientSessionId: session.clientSessionId,
@@ -3370,8 +3378,11 @@ var PollarClient = class {
3370
3378
  user: session.user,
3371
3379
  // The wire response still carries the legacy `publicKey` alias (kept for
3372
3380
  // older SDKs); the persisted session standardizes on `address` only.
3381
+ // The wire also still emits the legacy type `'custodial'` (unchanged for
3382
+ // SDKs ≤0.8.x); we remap it to `'internal'` here so the SDK surface and
3383
+ // persisted session speak one vocabulary while the wire stays compatible.
3373
3384
  wallet: {
3374
- type: w.type,
3385
+ type: w.type === "custodial" ? "internal" : w.type,
3375
3386
  address: w.address ?? w.publicKey ?? null,
3376
3387
  ...w.existsOnStellar !== void 0 ? { existsOnStellar: w.existsOnStellar } : {},
3377
3388
  ...w.createdAt !== void 0 ? { createdAt: w.createdAt } : {},
@@ -3395,7 +3406,7 @@ var PollarClient = class {
3395
3406
  this._scheduleNextRefresh();
3396
3407
  }
3397
3408
  async _clearSession() {
3398
- console.info("[PollarClient] Session cleared");
3409
+ this._log.info("[PollarClient] Session cleared");
3399
3410
  this._clearRefreshTimer();
3400
3411
  this._session = null;
3401
3412
  this._profile = null;
@@ -3404,7 +3415,7 @@ var PollarClient = class {
3404
3415
  try {
3405
3416
  await this._keyManager.reset();
3406
3417
  } catch (err) {
3407
- console.warn("[PollarClient] KeyManager reset failed during clearSession", err);
3418
+ this._log.warn("[PollarClient] KeyManager reset failed during clearSession", err);
3408
3419
  }
3409
3420
  await removeStorage(this._storage, this.apiKeyHash);
3410
3421
  this._transactionState = null;
@@ -3416,17 +3427,17 @@ var PollarClient = class {
3416
3427
  _setNetworkState(next) {
3417
3428
  this._networkState = next;
3418
3429
  const label = next.step === "connected" ? next.network : next.step;
3419
- console.info(`[PollarClient] network:${label}`);
3430
+ this._log.debug(`[PollarClient] network:${label}`);
3420
3431
  for (const cb of this._networkStateListeners) cb(next);
3421
3432
  }
3422
3433
  _setAuthState(next) {
3423
3434
  this._authState = next;
3424
- console.info(`[PollarClient] auth:${next.step}`);
3435
+ this._log.debug(`[PollarClient] auth:${next.step}`);
3425
3436
  for (const cb of this._authStateListeners) cb(next);
3426
3437
  }
3427
3438
  _setTransactionState(next) {
3428
3439
  this._transactionState = next;
3429
- console.info(`[PollarClient] transaction:${next.step}`);
3440
+ this._log.debug(`[PollarClient] transaction:${next.step}`);
3430
3441
  for (const cb of this._transactionStateListeners) cb(next);
3431
3442
  }
3432
3443
  /**
@@ -3530,7 +3541,6 @@ var WebCryptoKeyManager = class {
3530
3541
  if (this.keyPair) return;
3531
3542
  if (!this._initPromise) {
3532
3543
  this._initPromise = this._doInit().catch((err) => {
3533
- console.error("[PollarClient:keys] WebCryptoKeyManager init failed", err);
3534
3544
  this._initPromise = null;
3535
3545
  throw err;
3536
3546
  });
@@ -3666,6 +3676,6 @@ _setDefaultKeyManagerFactory((storage, apiKey) => {
3666
3676
  return new NobleKeyManager(storage, apiKey);
3667
3677
  });
3668
3678
 
3669
- export { AUTH_ERROR_CODES, AlbedoAdapter, FreighterAdapter, NobleKeyManager, 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 };
3679
+ export { AUTH_ERROR_CODES, AlbedoAdapter, FreighterAdapter, NobleKeyManager, POLLAR_CORE_VERSION, PollarClient, StellarClient, WalletType, WebCryptoKeyManager, buildProof, canonicalEcJwk, claimDistributionRule, computeJwkThumbprint, createLocalStorageAdapter, createLogger, createMemoryAdapter, createOffRamp, createOnRamp, defaultKeyManager, defaultStorage, getKycProviders, getKycStatus, getRampTransaction, getRampsQuote, isValidSession, listDistributionRules, normalizeHtu, pollKycStatus, pollRampTransaction, resolveKyc, startKyc };
3670
3680
  //# sourceMappingURL=index.rn.mjs.map
3671
3681
  //# sourceMappingURL=index.rn.mjs.map