@pollar/core 0.8.2 → 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
@@ -184,17 +184,6 @@ function defaultKeyManager(storage, apiKey) {
184
184
  }
185
185
  return _factory(storage, apiKey);
186
186
  }
187
- async function sha256(data) {
188
- return sha256$1(data);
189
- }
190
-
191
- // src/lib/api-key-hash.ts
192
- async function hashApiKey(apiKey) {
193
- const digest = await sha256(new TextEncoder().encode(apiKey));
194
- let hex = "";
195
- for (let i = 0; i < 4; i++) hex += digest[i].toString(16).padStart(2, "0");
196
- return hex;
197
- }
198
187
 
199
188
  // src/lib/base64url.ts
200
189
  var ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
@@ -232,6 +221,17 @@ function base64urlEncode(bytes) {
232
221
  function base64urlEncodeString(s) {
233
222
  return base64urlEncode(new TextEncoder().encode(s));
234
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
+ }
235
235
 
236
236
  // src/keys/thumbprint.ts
237
237
  async function computeJwkThumbprint(jwk) {
@@ -242,11 +242,14 @@ async function computeJwkThumbprint(jwk) {
242
242
  const digest = await sha256(new TextEncoder().encode(canonical));
243
243
  return base64urlEncode(digest);
244
244
  }
245
+ function toBase64url(value) {
246
+ return value.replace(/\+/g, "-").replace(/\//g, "_").replace(/[^A-Za-z0-9_-]/g, "");
247
+ }
245
248
  function canonicalEcJwk(jwk) {
246
249
  if (jwk.kty !== "EC" || jwk.crv !== "P-256" || typeof jwk.x !== "string" || typeof jwk.y !== "string") {
247
250
  throw new Error("[PollarClient:thumbprint] Source JWK is not an EC P-256 public key");
248
251
  }
249
- 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) };
250
253
  }
251
254
 
252
255
  // src/keys/web-crypto.ts
@@ -260,7 +263,7 @@ function openDb() {
260
263
  return;
261
264
  }
262
265
  const req = indexedDB.open(DB_NAME, DB_VERSION);
263
- req.onerror = () => reject(req.error ?? new Error("IDB open failed"));
266
+ req.onerror = () => reject(req.error ?? new Error("[PollarClient:keys] IDB open failed"));
264
267
  req.onsuccess = () => resolve(req.result);
265
268
  req.onupgradeneeded = () => {
266
269
  const db = req.result;
@@ -273,7 +276,7 @@ function openDb() {
273
276
  function awaitTx(req) {
274
277
  return new Promise((resolve, reject) => {
275
278
  req.onsuccess = () => resolve(req.result);
276
- req.onerror = () => reject(req.error ?? new Error("IDB request failed"));
279
+ req.onerror = () => reject(req.error ?? new Error("[PollarClient:keys] IDB request failed"));
277
280
  });
278
281
  }
279
282
  async function dbGet(key) {
@@ -368,10 +371,39 @@ var WebCryptoKeyManager = class {
368
371
  }
369
372
  }
370
373
  this.keyPair = pair;
371
- const exported = await globalThis.crypto.subtle.exportKey("jwk", pair.publicKey);
372
- this.publicJwk = canonicalEcJwk(exported);
374
+ this.publicJwk = await this._exportPublicJwk(pair.publicKey);
373
375
  this.thumbprint = await computeJwkThumbprint(this.publicJwk);
374
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
+ }
375
407
  async reset() {
376
408
  try {
377
409
  if (this.apiKeyHash) await dbDelete(this.apiKeyHash);
@@ -1129,6 +1161,9 @@ function defaultStorage(options = {}) {
1129
1161
  return createLocalStorageAdapter(options);
1130
1162
  }
1131
1163
 
1164
+ // src/version.ts
1165
+ var POLLAR_CORE_VERSION = "0.9.0-rc.0" ;
1166
+
1132
1167
  // src/visibility/noop.ts
1133
1168
  function createNoopVisibilityProvider() {
1134
1169
  return {
@@ -1193,6 +1228,7 @@ var AUTH_ERROR_CODES = {
1193
1228
  WALLET_CONNECT_FAILED: "WALLET_CONNECT_FAILED",
1194
1229
  WALLET_AUTH_FAILED: "WALLET_AUTH_FAILED",
1195
1230
  WALLET_RESOLVER_TIMEOUT: "WALLET_RESOLVER_TIMEOUT",
1231
+ PASSKEY_FAILED: "PASSKEY_FAILED",
1196
1232
  UNEXPECTED_ERROR: "UNEXPECTED_ERROR"
1197
1233
  };
1198
1234
  var PollarFlowError = class extends Error {
@@ -1238,7 +1274,7 @@ var FreighterAdapter = class {
1238
1274
  if (!userInfo?.publicKey) {
1239
1275
  throw new Error("Failed to get user information from Freighter");
1240
1276
  }
1241
- return { address: userInfo.publicKey, publicKey: userInfo.publicKey };
1277
+ return { address: userInfo.publicKey };
1242
1278
  }
1243
1279
  async disconnect() {
1244
1280
  }
@@ -1276,6 +1312,19 @@ var FreighterAdapter = class {
1276
1312
  };
1277
1313
 
1278
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
+ }
1279
1328
  function openAlbedoPopup(url) {
1280
1329
  const popup = window.open(url, "albedo", "width=420,height=720,resizable=yes,scrollbars=yes");
1281
1330
  if (!popup) {
@@ -1314,7 +1363,13 @@ function waitForAlbedoResult() {
1314
1363
  });
1315
1364
  }
1316
1365
  var AlbedoAdapter = class {
1317
- 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;
1318
1373
  this.type = "albedo" /* ALBEDO */;
1319
1374
  }
1320
1375
  async isAvailable() {
@@ -1324,7 +1379,7 @@ var AlbedoAdapter = class {
1324
1379
  const url = new URL("https://albedo.link");
1325
1380
  url.searchParams.set("intent", "public-key");
1326
1381
  url.searchParams.set("app_name", "Pollar");
1327
- url.searchParams.set("network", "testnet");
1382
+ url.searchParams.set("network", this.network);
1328
1383
  url.searchParams.set("callback", `${window.location.origin}/albedo-callback`);
1329
1384
  url.searchParams.set("origin", window.location.origin);
1330
1385
  openAlbedoPopup(url.toString());
@@ -1332,7 +1387,7 @@ var AlbedoAdapter = class {
1332
1387
  if (!result.pubkey) {
1333
1388
  throw new Error("Albedo connection rejected");
1334
1389
  }
1335
- return { address: result.pubkey, publicKey: result.pubkey };
1390
+ return { address: result.pubkey };
1336
1391
  }
1337
1392
  async disconnect() {
1338
1393
  }
@@ -1342,12 +1397,12 @@ var AlbedoAdapter = class {
1342
1397
  async getNetwork() {
1343
1398
  throw new Error("Albedo does not expose network");
1344
1399
  }
1345
- async signTransaction(xdr, _options) {
1400
+ async signTransaction(xdr, options) {
1346
1401
  const url = new URL("https://albedo.link");
1347
1402
  url.searchParams.set("intent", "tx");
1348
1403
  url.searchParams.set("xdr", xdr);
1349
1404
  url.searchParams.set("app_name", "Pollar");
1350
- url.searchParams.set("network", "testnet");
1405
+ url.searchParams.set("network", albedoNetwork(options, this.network));
1351
1406
  url.searchParams.set("callback", window.location.href);
1352
1407
  url.searchParams.set("origin", window.location.origin);
1353
1408
  window.location.href = url.toString();
@@ -1360,7 +1415,7 @@ var AlbedoAdapter = class {
1360
1415
  url.searchParams.set("intent", "sign-auth-entry");
1361
1416
  url.searchParams.set("xdr", entryXdr);
1362
1417
  url.searchParams.set("app_name", "Pollar");
1363
- url.searchParams.set("network", "testnet");
1418
+ url.searchParams.set("network", this.network);
1364
1419
  url.searchParams.set("callback", window.location.href);
1365
1420
  url.searchParams.set("origin", window.location.origin);
1366
1421
  window.location.href = url.toString();
@@ -1447,8 +1502,12 @@ function isValidSession(value) {
1447
1502
  return false;
1448
1503
  }
1449
1504
  const w = wallet;
1450
- if (w["publicKey"] !== null && !isBoundedString(w["publicKey"], MAX_WALLET_PUBLIC_KEY)) {
1451
- 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");
1452
1511
  return false;
1453
1512
  }
1454
1513
  if (w["existsOnStellar"] !== void 0 && typeof w["existsOnStellar"] !== "boolean") {
@@ -1459,6 +1518,10 @@ function isValidSession(value) {
1459
1518
  console.warn("[PollarClient:session] Invalid session \u2014 wallet.createdAt must be a finite number if present");
1460
1519
  return false;
1461
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
+ }
1462
1525
  return true;
1463
1526
  }
1464
1527
  async function readStorage(storage, apiKeyHash) {
@@ -1466,6 +1529,12 @@ async function readStorage(storage, apiKeyHash) {
1466
1529
  if (!raw) return null;
1467
1530
  try {
1468
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
+ }
1469
1538
  if (!isValidSession(session)) {
1470
1539
  await storage.remove(sessionStorageKey(apiKeyHash));
1471
1540
  console.warn("[PollarClient:session] Stored session is invalid \u2014 clearing storage");
@@ -1556,7 +1625,7 @@ async function streamUntilFound(api, clientSessionId, check, retryDelayMs = 200,
1556
1625
  }));
1557
1626
  } catch (e) {
1558
1627
  if (e instanceof Error && e.name === "AbortError") throw e;
1559
- console.warn(e);
1628
+ console.warn("[PollarClient:stream] session-status request failed; will retry", e);
1560
1629
  }
1561
1630
  if (error || !data) {
1562
1631
  await sleep(backoff);
@@ -1596,7 +1665,7 @@ async function streamUntilFound(api, clientSessionId, check, retryDelayMs = 200,
1596
1665
  } catch (e) {
1597
1666
  if (e instanceof Error && e.name === "AbortError") throw e;
1598
1667
  if (e instanceof SessionStatusError) throw e;
1599
- console.warn(e);
1668
+ console.warn("[PollarClient:stream] session-status stream read failed; will retry", e);
1600
1669
  } finally {
1601
1670
  reader.releaseLock();
1602
1671
  }
@@ -1624,7 +1693,7 @@ async function pollUntilFound(baseUrl, clientSessionId, check, intervalMs = 500,
1624
1693
  envelope = await response.json().catch(() => null);
1625
1694
  } catch (e) {
1626
1695
  if (e instanceof Error && e.name === "AbortError") throw e;
1627
- console.warn(e);
1696
+ console.warn("[PollarClient:stream] session-status poll failed; will retry", e);
1628
1697
  }
1629
1698
  if (httpStatus === 404 || envelope?.code === "INVALID_CLIENT_SESSION_ID") {
1630
1699
  throw new SessionStatusError("INVALID_CLIENT_SESSION_ID");
@@ -1828,6 +1897,55 @@ async function loginOAuth(provider, deps) {
1828
1897
  await authenticate(clientSessionId, deps);
1829
1898
  }
1830
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
+
1831
1949
  // src/client/auth/walletFlow.ts
1832
1950
  function withSignal(promise, signal) {
1833
1951
  return Promise.race([
@@ -1854,12 +1972,12 @@ async function loginWallet(type, deps) {
1854
1972
  setAuthState({ step: "wallet_not_installed", walletType: type });
1855
1973
  return;
1856
1974
  }
1857
- const { publicKey } = await withSignal(adapter.connect(), signal);
1858
- connectedWallet = publicKey;
1975
+ const { address } = await withSignal(adapter.connect(), signal);
1976
+ connectedWallet = address;
1859
1977
  deps.storeWalletAdapter(adapter, type);
1860
1978
  setAuthState({ step: "authenticating_wallet" });
1861
1979
  const { data: walletData, error: walletError } = await api.POST("/auth/wallet", {
1862
- body: { clientSessionId, walletAddress: publicKey },
1980
+ body: { clientSessionId, walletAddress: address },
1863
1981
  signal
1864
1982
  });
1865
1983
  if (walletError || !walletData?.success) {
@@ -1924,8 +2042,12 @@ var PollarClient = class {
1924
2042
  this._transactionStateListeners = /* @__PURE__ */ new Set();
1925
2043
  this._txHistoryState = { step: "idle" };
1926
2044
  this._txHistoryStateListeners = /* @__PURE__ */ new Set();
2045
+ this._sessionsState = { step: "idle" };
2046
+ this._sessionsStateListeners = /* @__PURE__ */ new Set();
1927
2047
  this._walletBalanceState = { step: "idle" };
1928
2048
  this._walletBalanceStateListeners = /* @__PURE__ */ new Set();
2049
+ this._enabledAssetsState = { step: "idle" };
2050
+ this._enabledAssetsStateListeners = /* @__PURE__ */ new Set();
1929
2051
  this._authState = { step: "idle" };
1930
2052
  this._authStateListeners = /* @__PURE__ */ new Set();
1931
2053
  this._networkState = { step: "idle" };
@@ -1941,6 +2063,8 @@ var PollarClient = class {
1941
2063
  this._storageDegradeListeners = /* @__PURE__ */ new Set();
1942
2064
  this._walletAdapter = null;
1943
2065
  this._loginController = null;
2066
+ /** Aborts an in-flight `/auth/session/resume` on destroy() or re-trigger. */
2067
+ this._resumeController = null;
1944
2068
  this.apiKey = config.apiKey;
1945
2069
  this.id = randomUUID();
1946
2070
  this.basePath = `${config.baseUrl || "https://sdk.api.pollar.xyz"}/v1`;
@@ -1953,6 +2077,8 @@ var PollarClient = class {
1953
2077
  this._keyManager = config.keyManager ?? defaultKeyManager(this._storage, config.apiKey);
1954
2078
  this._walletAdapterResolver = config.walletAdapter ?? null;
1955
2079
  this._walletResolverTimeoutMs = config.walletResolverTimeoutMs ?? 5e3;
2080
+ this._passkey = config.passkey ?? null;
2081
+ this._passkeySign = config.passkeySign ?? null;
1956
2082
  this._deviceLabel = config.deviceLabel;
1957
2083
  this._visibilityProvider = config.visibilityProvider ?? defaultVisibilityProvider();
1958
2084
  this._maxIdleMs = config.maxIdleMs;
@@ -1966,7 +2092,9 @@ var PollarClient = class {
1966
2092
  this._initialized = Promise.resolve();
1967
2093
  return;
1968
2094
  }
1969
- 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
+ );
1970
2098
  this._initialized = this._initialize();
1971
2099
  }
1972
2100
  /**
@@ -2004,7 +2132,11 @@ var PollarClient = class {
2004
2132
  }
2005
2133
  await this._restoreSession();
2006
2134
  this._visibilityUnsubscribe = this._visibilityProvider.onChange((visible) => {
2007
- 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
+ }
2008
2140
  });
2009
2141
  }
2010
2142
  /** Detach the cross-tab storage listener and abort any in-flight login. */
@@ -2015,6 +2147,8 @@ var PollarClient = class {
2015
2147
  }
2016
2148
  this._loginController?.abort();
2017
2149
  this._loginController = null;
2150
+ this._resumeController?.abort();
2151
+ this._resumeController = null;
2018
2152
  this._clearRefreshTimer();
2019
2153
  if (this._visibilityUnsubscribe) {
2020
2154
  this._visibilityUnsubscribe();
@@ -2029,7 +2163,9 @@ var PollarClient = class {
2029
2163
  request.headers.set("x-pollar-api-key", self.apiKey);
2030
2164
  self._lastRequestAt = Date.now();
2031
2165
  await self._initialized;
2032
- if (request.body !== null) {
2166
+ const cacheMethod = request.method.toUpperCase();
2167
+ const cacheBodyAllowed = cacheMethod !== "GET" && cacheMethod !== "HEAD";
2168
+ if (cacheBodyAllowed && request.body != null) {
2033
2169
  try {
2034
2170
  self._requestBodyCache.set(request, await request.clone().arrayBuffer());
2035
2171
  } catch (err) {
@@ -2116,7 +2252,9 @@ var PollarClient = class {
2116
2252
  }
2117
2253
  }
2118
2254
  }
2119
- 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;
2120
2258
  const retried = new Request(originalRequest.url, {
2121
2259
  method: originalRequest.method,
2122
2260
  headers,
@@ -2160,19 +2298,26 @@ var PollarClient = class {
2160
2298
  throw err;
2161
2299
  }
2162
2300
  if (error || !data) {
2163
- console.warn("[PollarClient] /auth/refresh returned error", { error });
2301
+ console.error("[PollarClient] /auth/refresh returned error", { error });
2164
2302
  await this._clearSession();
2165
2303
  throw new Error("Refresh failed");
2166
2304
  }
2167
2305
  const successData = data;
2168
2306
  if (!successData.success || !successData.content?.token) {
2169
- 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
+ });
2170
2311
  await this._clearSession();
2171
2312
  throw new Error("Refresh response malformed");
2172
2313
  }
2173
2314
  const newToken = successData.content.token;
2174
2315
  if (typeof newToken.accessToken !== "string" || typeof newToken.refreshToken !== "string" || typeof newToken.expiresAt !== "number") {
2175
- 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
+ });
2176
2321
  await this._clearSession();
2177
2322
  throw new Error("Refresh response token shape invalid");
2178
2323
  }
@@ -2366,6 +2511,19 @@ var PollarClient = class {
2366
2511
  const controller = this._newController();
2367
2512
  loginWallet(type, this._flowDeps(controller.signal)).catch((err) => this._handleFlowError(err));
2368
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
+ }
2369
2527
  // ─── Cancel ───────────────────────────────────────────────────────────────
2370
2528
  cancelLogin() {
2371
2529
  this._loginController?.abort();
@@ -2428,6 +2586,29 @@ var PollarClient = class {
2428
2586
  }
2429
2587
  return data.content.sessions;
2430
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
+ }
2431
2612
  /**
2432
2613
  * Revoke a specific refresh-token family (a single device session). Use
2433
2614
  * `listSessions` to enumerate the familyIds. Revoking the current session
@@ -2504,16 +2685,19 @@ var PollarClient = class {
2504
2685
  cb(this._walletBalanceState);
2505
2686
  return () => this._walletBalanceStateListeners.delete(cb);
2506
2687
  }
2507
- async refreshBalance(publicKey) {
2508
- const pk = publicKey ?? this._session?.wallet?.publicKey;
2509
- 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) {
2510
2695
  this._setWalletBalanceState({ step: "error", message: "No wallet connected" });
2511
2696
  return;
2512
2697
  }
2513
2698
  this._setWalletBalanceState({ step: "loading" });
2514
2699
  try {
2515
- const network = this.getNetwork();
2516
- const { data, error } = await this._api.GET("/wallet/balance", { params: { query: { publicKey: pk, network } } });
2700
+ const { data, error } = await this._api.GET("/wallet/balance");
2517
2701
  if (!error && data?.success && data.content) {
2518
2702
  this._setWalletBalanceState({ step: "loaded", data: data.content });
2519
2703
  } else {
@@ -2523,6 +2707,53 @@ var PollarClient = class {
2523
2707
  this._setWalletBalanceState({ step: "error", message: "Failed to load balance" });
2524
2708
  }
2525
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
+ }
2526
2757
  // ─── Transactions ─────────────────────────────────────────────────────────
2527
2758
  /**
2528
2759
  * Builds an unsigned XDR. Drives `_setTransactionState` for modal-style UIs
@@ -2530,14 +2761,14 @@ var PollarClient = class {
2530
2761
  * inspect the result without subscribing to state changes.
2531
2762
  */
2532
2763
  async buildTx(operation, params, options) {
2533
- if (!this._session?.wallet?.publicKey) {
2764
+ if (!this._session?.wallet?.address) {
2534
2765
  const details = "No wallet connected";
2535
2766
  this._setTransactionState({ step: "error", phase: "building", details });
2536
2767
  return { status: "error", details };
2537
2768
  }
2538
2769
  const body = {
2539
2770
  network: this.getNetwork(),
2540
- publicKey: this._session.wallet.publicKey,
2771
+ address: this._session.wallet.address,
2541
2772
  operation,
2542
2773
  params,
2543
2774
  options: options ?? {}
@@ -2578,7 +2809,7 @@ var PollarClient = class {
2578
2809
  const buildData = this._currentBuildData();
2579
2810
  this._setTransactionState({ step: "signing", ...buildData && { buildData } });
2580
2811
  if (this._walletAdapter) {
2581
- const accountToSign = this._session?.wallet?.publicKey;
2812
+ const accountToSign = this._session?.wallet?.address;
2582
2813
  const signOpts = accountToSign ? { networkPassphrase: this._networkPassphrase(), accountToSign } : { networkPassphrase: this._networkPassphrase() };
2583
2814
  try {
2584
2815
  const { signedTxXdr } = await this._walletAdapter.signTransaction(unsignedXdr, signOpts);
@@ -2599,10 +2830,10 @@ var PollarClient = class {
2599
2830
  return { status: "error", ...details && { details } };
2600
2831
  }
2601
2832
  }
2602
- const publicKey = this._session?.wallet?.publicKey ?? "";
2833
+ const address = this._session?.wallet?.address ?? "";
2603
2834
  try {
2604
2835
  const { data, error } = await this._api.POST("/tx/sign", {
2605
- body: { network: this.getNetwork(), publicKey, unsignedXdr }
2836
+ body: { network: this.getNetwork(), address, unsignedXdr }
2606
2837
  });
2607
2838
  if (!error && data?.success && data.content?.signedXdr) {
2608
2839
  const { signedXdr, idempotencyKey } = data.content;
@@ -2655,12 +2886,12 @@ var PollarClient = class {
2655
2886
  const buildData = this._currentBuildData();
2656
2887
  const outcomeExtra = buildData ? { buildData } : {};
2657
2888
  this._setTransactionState({ step: "submitting", signedXdr, ...buildData && { buildData } });
2658
- const publicKey = this._session?.wallet?.publicKey ?? "";
2889
+ const address = this._session?.wallet?.address ?? "";
2659
2890
  try {
2660
2891
  const { data, error } = await this._api.POST("/tx/submit", {
2661
2892
  body: {
2662
2893
  network: this.getNetwork(),
2663
- publicKey,
2894
+ address,
2664
2895
  signedXdr,
2665
2896
  ...opts?.submissionToken && { idempotencyKey: opts.submissionToken }
2666
2897
  }
@@ -2720,6 +2951,19 @@ var PollarClient = class {
2720
2951
  * `success` (ledger-confirmed), or `error[phase: 'signing-submitting']`.
2721
2952
  */
2722
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
+ }
2723
2967
  if (this._walletAdapter) {
2724
2968
  const signed = await this.signTx(unsignedXdr);
2725
2969
  if (signed.status === "error") {
@@ -2737,7 +2981,7 @@ var PollarClient = class {
2737
2981
  this._setTransactionState({ step: "signing-submitting", ...buildData && { buildData } });
2738
2982
  const body = {
2739
2983
  network: this.getNetwork(),
2740
- publicKey: this._session?.wallet?.publicKey ?? "",
2984
+ address: this._session?.wallet?.address ?? "",
2741
2985
  unsignedXdr
2742
2986
  };
2743
2987
  try {
@@ -2806,14 +3050,20 @@ var PollarClient = class {
2806
3050
  * `signTx`, and `submitTx` separately instead.
2807
3051
  */
2808
3052
  async buildAndSignAndSubmitTx(operation, params, options) {
3053
+ if (this._session?.wallet?.type === "smart") {
3054
+ return this._runSmartTx(operation, params, options);
3055
+ }
2809
3056
  if (this._walletAdapter) {
2810
3057
  const built = await this.buildTx(operation, params, options);
2811
3058
  if (built.status === "error") {
2812
3059
  return { status: "error", ...built.details && { details: built.details } };
2813
3060
  }
3061
+ if (!built.buildData.unsignedXdr) {
3062
+ return { status: "error", details: "build returned no unsigned transaction" };
3063
+ }
2814
3064
  return this.signAndSubmitTx(built.buildData.unsignedXdr);
2815
3065
  }
2816
- if (!this._session?.wallet?.publicKey) {
3066
+ if (!this._session?.wallet?.address) {
2817
3067
  this._setTransactionState({ step: "error", phase: "building-signing-submitting", details: "No wallet connected" });
2818
3068
  return { status: "error", details: "No wallet connected" };
2819
3069
  }
@@ -2822,7 +3072,7 @@ var PollarClient = class {
2822
3072
  const { data, error } = await this._api.POST("/tx/build-sign-submit", {
2823
3073
  body: {
2824
3074
  network: this.getNetwork(),
2825
- publicKey: this._session.wallet.publicKey,
3075
+ address: this._session.wallet.address,
2826
3076
  operation,
2827
3077
  params,
2828
3078
  options: options ?? {}
@@ -2866,6 +3116,113 @@ var PollarClient = class {
2866
3116
  async runTx(operation, params, options) {
2867
3117
  return this.buildAndSignAndSubmitTx(operation, params, options);
2868
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
+ }
2869
3226
  // ─── App config ───────────────────────────────────────────────────────────
2870
3227
  async getAppConfig() {
2871
3228
  try {
@@ -2919,10 +3276,18 @@ var PollarClient = class {
2919
3276
  this._txHistoryState = next;
2920
3277
  for (const cb of this._txHistoryStateListeners) cb(next);
2921
3278
  }
3279
+ _setSessionsState(next) {
3280
+ this._sessionsState = next;
3281
+ for (const cb of this._sessionsStateListeners) cb(next);
3282
+ }
2922
3283
  _setWalletBalanceState(next) {
2923
3284
  this._walletBalanceState = next;
2924
3285
  for (const cb of this._walletBalanceStateListeners) cb(next);
2925
3286
  }
3287
+ _setEnabledAssetsState(next) {
3288
+ this._enabledAssetsState = next;
3289
+ for (const cb of this._enabledAssetsStateListeners) cb(next);
3290
+ }
2926
3291
  // ─── Private ──────────────────────────────────────────────────────────────
2927
3292
  _newController() {
2928
3293
  this._loginController?.abort();
@@ -2947,6 +3312,7 @@ var PollarClient = class {
2947
3312
  this._walletAdapter = adapter;
2948
3313
  await writeWalletType(this._storage, this.apiKeyHash, id);
2949
3314
  },
3315
+ ...this._passkey ? { passkey: this._passkey } : {},
2950
3316
  ...this._deviceLabel ? { deviceLabel: this._deviceLabel } : {}
2951
3317
  };
2952
3318
  }
@@ -2976,7 +3342,7 @@ var PollarClient = class {
2976
3342
  }
2977
3343
  }
2978
3344
  if (id === "freighter" /* FREIGHTER */) return new FreighterAdapter();
2979
- if (id === "albedo" /* ALBEDO */) return new AlbedoAdapter();
3345
+ if (id === "albedo" /* ALBEDO */) return new AlbedoAdapter(this.getNetwork() === "mainnet" ? "public" : "testnet");
2980
3346
  throw new Error(
2981
3347
  `[PollarClient] No wallet adapter configured for "${id}". Pass a walletAdapter resolver in PollarClientConfig.`
2982
3348
  );
@@ -3017,21 +3383,66 @@ var PollarClient = class {
3017
3383
  }
3018
3384
  }
3019
3385
  console.info("[PollarClient] Session restored from storage");
3020
- this._setAuthState({ step: "authenticated", session: this._session });
3386
+ this._setAuthState({ step: "authenticated", session: this._session, verified: false });
3021
3387
  this._scheduleNextRefresh();
3388
+ void this._resume();
3022
3389
  } else {
3023
3390
  console.info("[PollarClient] No session in storage");
3024
3391
  }
3025
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
+ }
3026
3426
  async _storeSession(session) {
3027
3427
  console.info("[PollarClient] Session stored");
3428
+ const w = session.wallet;
3028
3429
  const persisted = {
3029
3430
  clientSessionId: session.clientSessionId,
3030
3431
  userId: session.userId ?? null,
3031
3432
  status: session.status,
3032
3433
  token: session.token,
3033
3434
  user: session.user,
3034
- 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
+ }
3035
3446
  };
3036
3447
  this._session = persisted;
3037
3448
  if (session.data) {
@@ -3044,7 +3455,7 @@ var PollarClient = class {
3044
3455
  };
3045
3456
  }
3046
3457
  await writeStorage(this._storage, this.apiKeyHash, persisted);
3047
- this._setAuthState({ step: "authenticated", session: persisted });
3458
+ this._setAuthState({ step: "authenticated", session: persisted, verified: true });
3048
3459
  this._scheduleNextRefresh();
3049
3460
  }
3050
3461
  async _clearSession() {
@@ -3127,6 +3538,6 @@ var StellarClient = class {
3127
3538
  // src/index.ts
3128
3539
  _setDefaultKeyManagerFactory((_storage, apiKey) => new WebCryptoKeyManager(apiKey));
3129
3540
 
3130
- 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 };
3131
3542
  //# sourceMappingURL=index.mjs.map
3132
3543
  //# sourceMappingURL=index.mjs.map