@pollar/core 0.5.0 → 0.5.3

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
@@ -765,8 +765,176 @@ var PollarFlowError = class extends Error {
765
765
  }
766
766
  };
767
767
 
768
+ // src/wallets/FreighterAdapter.ts
769
+ var import_freighter_api = __toESM(require_index_min());
770
+
771
+ // src/wallets/types.ts
772
+ var WalletType = /* @__PURE__ */ ((WalletType2) => {
773
+ WalletType2["FREIGHTER"] = "freighter";
774
+ WalletType2["ALBEDO"] = "albedo";
775
+ return WalletType2;
776
+ })(WalletType || {});
777
+
778
+ // src/wallets/FreighterAdapter.ts
779
+ var FreighterAdapter = class {
780
+ constructor() {
781
+ this.type = "freighter" /* FREIGHTER */;
782
+ }
783
+ async isAvailable() {
784
+ try {
785
+ return await (0, import_freighter_api.isConnected)();
786
+ } catch {
787
+ return false;
788
+ }
789
+ }
790
+ async connect() {
791
+ const connected = await (0, import_freighter_api.isConnected)();
792
+ if (!connected) {
793
+ throw new Error("Freighter wallet is not installed");
794
+ }
795
+ const allowed = await (0, import_freighter_api.isAllowed)();
796
+ if (!allowed) {
797
+ await (0, import_freighter_api.setAllowed)();
798
+ }
799
+ const userInfo = await (0, import_freighter_api.getUserInfo)();
800
+ if (!userInfo?.publicKey) {
801
+ throw new Error("Failed to get user information from Freighter");
802
+ }
803
+ return { address: userInfo.publicKey, publicKey: userInfo.publicKey };
804
+ }
805
+ async disconnect() {
806
+ }
807
+ async getPublicKey() {
808
+ try {
809
+ const allowed = await (0, import_freighter_api.isAllowed)();
810
+ if (!allowed) return null;
811
+ const userInfo = await (0, import_freighter_api.getUserInfo)();
812
+ return userInfo?.publicKey ?? null;
813
+ } catch {
814
+ return null;
815
+ }
816
+ }
817
+ async getNetwork() {
818
+ return (0, import_freighter_api.getNetwork)();
819
+ }
820
+ async signTransaction(xdr, options) {
821
+ const result = await (0, import_freighter_api.signTransaction)(xdr, {
822
+ network: options?.network,
823
+ networkPassphrase: options?.networkPassphrase,
824
+ accountToSign: options?.accountToSign
825
+ });
826
+ if (!result || typeof result !== "string") {
827
+ throw new Error("Invalid response from Freighter");
828
+ }
829
+ return { signedTxXdr: result };
830
+ }
831
+ async signAuthEntry(entryXdr, options) {
832
+ const result = await (0, import_freighter_api.signAuthEntry)(entryXdr, { accountToSign: options?.accountToSign });
833
+ if (!result || typeof result !== "string") {
834
+ throw new Error("Invalid response from Freighter");
835
+ }
836
+ return { signedAuthEntry: result };
837
+ }
838
+ };
839
+
840
+ // src/wallets/AlbedoAdapter.ts
841
+ function openAlbedoPopup(url) {
842
+ const popup = window.open(url, "albedo", "width=420,height=720,resizable=yes,scrollbars=yes");
843
+ if (!popup) {
844
+ throw new Error("Failed to open Albedo popup (blocked by browser)");
845
+ }
846
+ return popup;
847
+ }
848
+ function waitForAlbedoPopup() {
849
+ return new Promise((resolve, reject) => {
850
+ const timeout = setTimeout(() => reject(new Error("Albedo response timeout")), 2 * 60 * 1e3);
851
+ function handler(event) {
852
+ if (event.origin !== window.location.origin || event.data?.type !== "ALBEDO_RESULT") return;
853
+ clearTimeout(timeout);
854
+ window.removeEventListener("message", handler);
855
+ resolve(event.data.payload);
856
+ }
857
+ window.addEventListener("message", handler);
858
+ });
859
+ }
860
+ function waitForAlbedoResult() {
861
+ return new Promise((resolve, reject) => {
862
+ const timeout = setTimeout(() => reject(new Error("Albedo response timeout")), 2 * 60 * 1e3);
863
+ const parseResult = () => {
864
+ const params = new URLSearchParams(window.location.search);
865
+ if (!params.has("pubkey") && !params.has("signed_envelope_xdr") && !params.has("signed_xdr")) return;
866
+ clearTimeout(timeout);
867
+ const result = {};
868
+ params.forEach((value, key) => {
869
+ result[key] = value;
870
+ });
871
+ window.history.replaceState({}, document.title, window.location.pathname);
872
+ resolve(result);
873
+ };
874
+ parseResult();
875
+ window.addEventListener("popstate", parseResult);
876
+ });
877
+ }
878
+ var AlbedoAdapter = class {
879
+ constructor() {
880
+ this.type = "albedo" /* ALBEDO */;
881
+ }
882
+ async isAvailable() {
883
+ return typeof window !== "undefined";
884
+ }
885
+ async connect() {
886
+ const url = new URL("https://albedo.link");
887
+ url.searchParams.set("intent", "public-key");
888
+ url.searchParams.set("app_name", "Pollar");
889
+ url.searchParams.set("network", "testnet");
890
+ url.searchParams.set("callback", `${window.location.origin}/albedo-callback`);
891
+ url.searchParams.set("origin", window.location.origin);
892
+ openAlbedoPopup(url.toString());
893
+ const result = await waitForAlbedoPopup();
894
+ if (!result.pubkey) {
895
+ throw new Error("Albedo connection rejected");
896
+ }
897
+ return { address: result.pubkey, publicKey: result.pubkey };
898
+ }
899
+ async disconnect() {
900
+ }
901
+ async getPublicKey() {
902
+ return null;
903
+ }
904
+ async getNetwork() {
905
+ throw new Error("Albedo does not expose network");
906
+ }
907
+ async signTransaction(xdr, _options) {
908
+ const url = new URL("https://albedo.link");
909
+ url.searchParams.set("intent", "tx");
910
+ url.searchParams.set("xdr", xdr);
911
+ url.searchParams.set("app_name", "Pollar");
912
+ url.searchParams.set("network", "testnet");
913
+ url.searchParams.set("callback", window.location.href);
914
+ url.searchParams.set("origin", window.location.origin);
915
+ window.location.href = url.toString();
916
+ const result = await waitForAlbedoResult();
917
+ if (!result.signed_envelope_xdr) throw new Error("Albedo signing rejected");
918
+ return { signedTxXdr: result.signed_envelope_xdr };
919
+ }
920
+ async signAuthEntry(entryXdr, _options) {
921
+ const url = new URL("https://albedo.link");
922
+ url.searchParams.set("intent", "sign-auth-entry");
923
+ url.searchParams.set("xdr", entryXdr);
924
+ url.searchParams.set("app_name", "Pollar");
925
+ url.searchParams.set("network", "testnet");
926
+ url.searchParams.set("callback", window.location.href);
927
+ url.searchParams.set("origin", window.location.origin);
928
+ window.location.href = url.toString();
929
+ const result = await waitForAlbedoResult();
930
+ if (!result.signed_xdr) throw new Error("Albedo auth entry signing rejected");
931
+ return { signedAuthEntry: result.signed_xdr };
932
+ }
933
+ };
934
+
768
935
  // src/client/session.ts
769
936
  var STORAGE_KEY = "pollar:session";
937
+ var WALLET_TYPE_KEY = "pollar:walletType";
770
938
  function isValidSession(value) {
771
939
  if (typeof value !== "object" || value === null) {
772
940
  console.warn("[PollarClient:session] Invalid session \u2014 value is not an object");
@@ -902,8 +1070,15 @@ function writeStorage(session) {
902
1070
  }
903
1071
  function removeStorage() {
904
1072
  localStorage.removeItem(STORAGE_KEY);
1073
+ localStorage.removeItem(WALLET_TYPE_KEY);
905
1074
  console.info("[PollarClient:session] Session removed from storage");
906
1075
  }
1076
+ function writeWalletType(type) {
1077
+ localStorage.setItem(WALLET_TYPE_KEY, type);
1078
+ }
1079
+ function readWalletType() {
1080
+ return localStorage.getItem(WALLET_TYPE_KEY);
1081
+ }
907
1082
 
908
1083
  // src/client/stream.ts
909
1084
  function abortableDelay(ms, signal) {
@@ -977,7 +1152,7 @@ async function streamUntilFound(api, clientSessionId, check, retryDelayMs = 200,
977
1152
  }
978
1153
 
979
1154
  // src/client/auth/authenticate.ts
980
- async function authenticate(clientSessionId, deps) {
1155
+ async function authenticate(clientSessionId, deps, expectedWallet) {
981
1156
  const { api, signal, setAuthState, storeSession, clearSession } = deps;
982
1157
  setAuthState({ step: "authenticating" });
983
1158
  await streamUntilFound(api, clientSessionId, (data2) => data2?.status === "READY", 200, signal);
@@ -986,6 +1161,16 @@ async function authenticate(clientSessionId, deps) {
986
1161
  signal
987
1162
  });
988
1163
  if (data?.code === "SDK_LOGIN_SUCCESS" && isValidSession(data?.content)) {
1164
+ if (expectedWallet && data.content.data.providers.wallet?.address !== expectedWallet) {
1165
+ setAuthState({
1166
+ step: "error",
1167
+ previousStep: "authenticating",
1168
+ message: "Wallet mismatch: session wallet does not match connected wallet",
1169
+ errorCode: AUTH_ERROR_CODES.WALLET_AUTH_FAILED
1170
+ });
1171
+ clearSession();
1172
+ return;
1173
+ }
989
1174
  storeSession(data.content);
990
1175
  } else {
991
1176
  setAuthState({
@@ -1103,173 +1288,6 @@ async function loginOAuth(provider, deps) {
1103
1288
  await authenticate(clientSessionId, deps);
1104
1289
  }
1105
1290
 
1106
- // src/wallets/FreighterAdapter.ts
1107
- var import_freighter_api = __toESM(require_index_min());
1108
-
1109
- // src/wallets/types.ts
1110
- var WalletType = /* @__PURE__ */ ((WalletType2) => {
1111
- WalletType2["FREIGHTER"] = "freighter";
1112
- WalletType2["ALBEDO"] = "albedo";
1113
- return WalletType2;
1114
- })(WalletType || {});
1115
-
1116
- // src/wallets/FreighterAdapter.ts
1117
- var FreighterAdapter = class {
1118
- constructor() {
1119
- this.type = "freighter" /* FREIGHTER */;
1120
- }
1121
- async isAvailable() {
1122
- try {
1123
- return await (0, import_freighter_api.isConnected)();
1124
- } catch {
1125
- return false;
1126
- }
1127
- }
1128
- async connect() {
1129
- const connected = await (0, import_freighter_api.isConnected)();
1130
- if (!connected) {
1131
- throw new Error("Freighter wallet is not installed");
1132
- }
1133
- const allowed = await (0, import_freighter_api.isAllowed)();
1134
- if (!allowed) {
1135
- await (0, import_freighter_api.setAllowed)();
1136
- }
1137
- const userInfo = await (0, import_freighter_api.getUserInfo)();
1138
- if (!userInfo?.publicKey) {
1139
- throw new Error("Failed to get user information from Freighter");
1140
- }
1141
- return { address: userInfo.publicKey, publicKey: userInfo.publicKey };
1142
- }
1143
- async disconnect() {
1144
- }
1145
- async getPublicKey() {
1146
- try {
1147
- const allowed = await (0, import_freighter_api.isAllowed)();
1148
- if (!allowed) return null;
1149
- const userInfo = await (0, import_freighter_api.getUserInfo)();
1150
- return userInfo?.publicKey ?? null;
1151
- } catch {
1152
- return null;
1153
- }
1154
- }
1155
- async getNetwork() {
1156
- return (0, import_freighter_api.getNetwork)();
1157
- }
1158
- async signTransaction(xdr, options) {
1159
- const result = await (0, import_freighter_api.signTransaction)(xdr, {
1160
- network: options?.network,
1161
- networkPassphrase: options?.networkPassphrase,
1162
- accountToSign: options?.accountToSign
1163
- });
1164
- if (!result || typeof result !== "string") {
1165
- throw new Error("Invalid response from Freighter");
1166
- }
1167
- return { signedTxXdr: result };
1168
- }
1169
- async signAuthEntry(entryXdr, options) {
1170
- const result = await (0, import_freighter_api.signAuthEntry)(entryXdr, { accountToSign: options?.accountToSign });
1171
- if (!result || typeof result !== "string") {
1172
- throw new Error("Invalid response from Freighter");
1173
- }
1174
- return { signedAuthEntry: result };
1175
- }
1176
- };
1177
-
1178
- // src/wallets/AlbedoAdapter.ts
1179
- function openAlbedoPopup(url) {
1180
- const popup = window.open(url, "albedo", "width=420,height=720,resizable=yes,scrollbars=yes");
1181
- if (!popup) {
1182
- throw new Error("Failed to open Albedo popup (blocked by browser)");
1183
- }
1184
- return popup;
1185
- }
1186
- function waitForAlbedoPopup() {
1187
- return new Promise((resolve, reject) => {
1188
- const timeout = setTimeout(() => reject(new Error("Albedo response timeout")), 2 * 60 * 1e3);
1189
- function handler(event) {
1190
- if (event.origin !== window.location.origin || event.data?.type !== "ALBEDO_RESULT") return;
1191
- clearTimeout(timeout);
1192
- window.removeEventListener("message", handler);
1193
- resolve(event.data.payload);
1194
- }
1195
- window.addEventListener("message", handler);
1196
- });
1197
- }
1198
- function waitForAlbedoResult() {
1199
- return new Promise((resolve, reject) => {
1200
- const timeout = setTimeout(() => reject(new Error("Albedo response timeout")), 2 * 60 * 1e3);
1201
- const parseResult = () => {
1202
- const params = new URLSearchParams(window.location.search);
1203
- if (!params.has("pubkey") && !params.has("signed_envelope_xdr") && !params.has("signed_xdr")) return;
1204
- clearTimeout(timeout);
1205
- const result = {};
1206
- params.forEach((value, key) => {
1207
- result[key] = value;
1208
- });
1209
- window.history.replaceState({}, document.title, window.location.pathname);
1210
- resolve(result);
1211
- };
1212
- parseResult();
1213
- window.addEventListener("popstate", parseResult);
1214
- });
1215
- }
1216
- var AlbedoAdapter = class {
1217
- constructor() {
1218
- this.type = "albedo" /* ALBEDO */;
1219
- }
1220
- async isAvailable() {
1221
- return typeof window !== "undefined";
1222
- }
1223
- async connect() {
1224
- const url = new URL("https://albedo.link");
1225
- url.searchParams.set("intent", "public-key");
1226
- url.searchParams.set("app_name", "Pollar");
1227
- url.searchParams.set("network", "testnet");
1228
- url.searchParams.set("callback", `${window.location.origin}/albedo-callback`);
1229
- url.searchParams.set("origin", window.location.origin);
1230
- openAlbedoPopup(url.toString());
1231
- const result = await waitForAlbedoPopup();
1232
- if (!result.pubkey) {
1233
- throw new Error("Albedo connection rejected");
1234
- }
1235
- return { address: result.pubkey, publicKey: result.pubkey };
1236
- }
1237
- async disconnect() {
1238
- }
1239
- async getPublicKey() {
1240
- return null;
1241
- }
1242
- async getNetwork() {
1243
- throw new Error("Albedo does not expose network");
1244
- }
1245
- async signTransaction(xdr, _options) {
1246
- const url = new URL("https://albedo.link");
1247
- url.searchParams.set("intent", "tx");
1248
- url.searchParams.set("xdr", xdr);
1249
- url.searchParams.set("app_name", "Pollar");
1250
- url.searchParams.set("network", "testnet");
1251
- url.searchParams.set("callback", window.location.href);
1252
- url.searchParams.set("origin", window.location.origin);
1253
- window.location.href = url.toString();
1254
- const result = await waitForAlbedoResult();
1255
- if (!result.signed_envelope_xdr) throw new Error("Albedo signing rejected");
1256
- return { signedTxXdr: result.signed_envelope_xdr };
1257
- }
1258
- async signAuthEntry(entryXdr, _options) {
1259
- const url = new URL("https://albedo.link");
1260
- url.searchParams.set("intent", "sign-auth-entry");
1261
- url.searchParams.set("xdr", entryXdr);
1262
- url.searchParams.set("app_name", "Pollar");
1263
- url.searchParams.set("network", "testnet");
1264
- url.searchParams.set("callback", window.location.href);
1265
- url.searchParams.set("origin", window.location.origin);
1266
- window.location.href = url.toString();
1267
- const result = await waitForAlbedoResult();
1268
- if (!result.signed_xdr) throw new Error("Albedo auth entry signing rejected");
1269
- return { signedAuthEntry: result.signed_xdr };
1270
- }
1271
- };
1272
-
1273
1291
  // src/client/auth/walletFlow.ts
1274
1292
  function withSignal(promise, signal) {
1275
1293
  return Promise.race([
@@ -1287,6 +1305,7 @@ async function loginWallet(type, deps) {
1287
1305
  const { api, signal, setAuthState } = deps;
1288
1306
  const clientSessionId = await createAuthSession(deps);
1289
1307
  if (!clientSessionId) return;
1308
+ let connectedWallet;
1290
1309
  try {
1291
1310
  setAuthState({ step: "connecting_wallet", walletType: type });
1292
1311
  const adapter = type === "freighter" /* FREIGHTER */ ? new FreighterAdapter() : new AlbedoAdapter();
@@ -1296,7 +1315,8 @@ async function loginWallet(type, deps) {
1296
1315
  return;
1297
1316
  }
1298
1317
  const { publicKey } = await withSignal(adapter.connect(), signal);
1299
- deps.storeWalletAdapter(adapter);
1318
+ connectedWallet = publicKey;
1319
+ deps.storeWalletAdapter(adapter, type);
1300
1320
  setAuthState({ step: "authenticating_wallet" });
1301
1321
  const { data: walletData, error: walletError } = await api.POST("/auth/wallet", {
1302
1322
  body: { clientSessionId, walletAddress: publicKey },
@@ -1320,7 +1340,7 @@ async function loginWallet(type, deps) {
1320
1340
  });
1321
1341
  return;
1322
1342
  }
1323
- await authenticate(clientSessionId, deps);
1343
+ await authenticate(clientSessionId, deps, connectedWallet);
1324
1344
  }
1325
1345
 
1326
1346
  // src/client/client.ts
@@ -1337,6 +1357,8 @@ var PollarClient = class {
1337
1357
  this._transactionStateListeners = /* @__PURE__ */ new Set();
1338
1358
  this._txHistoryState = { step: "idle" };
1339
1359
  this._txHistoryStateListeners = /* @__PURE__ */ new Set();
1360
+ this._walletBalanceState = { step: "idle" };
1361
+ this._walletBalanceStateListeners = /* @__PURE__ */ new Set();
1340
1362
  this._authState = { step: "idle" };
1341
1363
  this._authStateListeners = /* @__PURE__ */ new Set();
1342
1364
  this._networkState = { step: "idle" };
@@ -1497,10 +1519,6 @@ var PollarClient = class {
1497
1519
  return () => this._transactionStateListeners.delete(cb);
1498
1520
  }
1499
1521
  // ─── Tx history ──────────────────────────────────────────────────────────
1500
- _setTxHistoryState(next) {
1501
- this._txHistoryState = next;
1502
- for (const cb of this._txHistoryStateListeners) cb(next);
1503
- }
1504
1522
  getTxHistoryState() {
1505
1523
  return this._txHistoryState;
1506
1524
  }
@@ -1524,13 +1542,32 @@ var PollarClient = class {
1524
1542
  }
1525
1543
  }
1526
1544
  // ─── Wallet balance ───────────────────────────────────────────────────────
1527
- async getWalletBalance(publicKey) {
1545
+ getWalletBalanceState() {
1546
+ return this._walletBalanceState;
1547
+ }
1548
+ onWalletBalanceStateChange(cb) {
1549
+ this._walletBalanceStateListeners.add(cb);
1550
+ cb(this._walletBalanceState);
1551
+ return () => this._walletBalanceStateListeners.delete(cb);
1552
+ }
1553
+ async refreshBalance(publicKey) {
1528
1554
  const pk = publicKey ?? this._session?.wallet?.publicKey;
1529
- if (!pk) return null;
1530
- const network = this.getNetwork();
1531
- const { data, error } = await this._api.GET("/wallet/balance", { params: { query: { publicKey: pk, network } } });
1532
- if (!error && data?.success && data.content) return data.content;
1533
- return null;
1555
+ if (!pk) {
1556
+ this._setWalletBalanceState({ step: "error", message: "No wallet connected" });
1557
+ return;
1558
+ }
1559
+ this._setWalletBalanceState({ step: "loading" });
1560
+ try {
1561
+ const network = this.getNetwork();
1562
+ const { data, error } = await this._api.GET("/wallet/balance", { params: { query: { publicKey: pk, network } } });
1563
+ if (!error && data?.success && data.content) {
1564
+ this._setWalletBalanceState({ step: "loaded", data: data.content });
1565
+ } else {
1566
+ this._setWalletBalanceState({ step: "error", message: "Failed to load balance" });
1567
+ }
1568
+ } catch {
1569
+ this._setWalletBalanceState({ step: "error", message: "Failed to load balance" });
1570
+ }
1534
1571
  }
1535
1572
  // ─── Transactions ─────────────────────────────────────────────────────────
1536
1573
  async buildTx(operation, params, options) {
@@ -1558,27 +1595,29 @@ var PollarClient = class {
1558
1595
  this._setTransactionState({ step: "error" });
1559
1596
  }
1560
1597
  }
1598
+ getWalletType() {
1599
+ return this._walletAdapter?.type ?? null;
1600
+ }
1561
1601
  async signAndSubmitTx(unsignedXdr) {
1562
- if (this._transactionState?.step !== "built") {
1563
- throw new PollarFlowError(
1564
- `signAndSubmitTx() requires step 'built', current step is '${this._transactionState?.step ?? "none"}'`
1565
- );
1566
- }
1567
- const buildData = this._transactionState.buildData;
1568
- this._setTransactionState({ step: "signing", buildData });
1602
+ const state = this._transactionState;
1603
+ const buildData = state?.step === "built" ? state.buildData : state?.step === "error" ? state.buildData : void 0;
1604
+ const isBuiltFlow = !!buildData;
1605
+ const stateExtra = buildData ? { buildData } : { external: true };
1606
+ this._setTransactionState({ step: "signing", ...stateExtra });
1607
+ const accountToSign = isBuiltFlow ? this._session?.wallet?.publicKey : this._session?.data?.providers?.wallet?.address ?? this._session?.wallet?.publicKey;
1569
1608
  if (this._walletAdapter) {
1570
1609
  try {
1571
- const signOpts = this._session?.wallet?.publicKey ? { networkPassphrase: this._networkPassphrase(), accountToSign: this._session.wallet.publicKey } : { networkPassphrase: this._networkPassphrase() };
1610
+ const signOpts = accountToSign ? { networkPassphrase: this._networkPassphrase(), accountToSign } : { networkPassphrase: this._networkPassphrase() };
1572
1611
  const { signedTxXdr } = await this._walletAdapter.signTransaction(unsignedXdr, signOpts);
1573
1612
  const stellarClient = new StellarClient(this.getNetwork());
1574
1613
  const result = await stellarClient.submitTransaction(signedTxXdr);
1575
1614
  if (result.success) {
1576
- this._setTransactionState({ step: "success", buildData, hash: result.hash });
1615
+ this._setTransactionState({ step: "success", ...stateExtra, hash: result.hash });
1577
1616
  } else {
1578
- this._setTransactionState({ step: "error", ...buildData && { buildData }, details: result.errorCode });
1617
+ this._setTransactionState({ step: "error", ...stateExtra, details: result.errorCode });
1579
1618
  }
1580
1619
  } catch {
1581
- this._setTransactionState({ step: "error", ...buildData && { buildData } });
1620
+ this._setTransactionState({ step: "error", ...stateExtra });
1582
1621
  }
1583
1622
  return;
1584
1623
  }
@@ -1590,13 +1629,13 @@ var PollarClient = class {
1590
1629
  try {
1591
1630
  const { data, error } = await this._api.POST("/tx/sign-and-send", { body });
1592
1631
  if (!error && data?.success && data.content?.hash) {
1593
- this._setTransactionState({ step: "success", buildData, hash: data.content.hash });
1632
+ this._setTransactionState({ step: "success", ...stateExtra, hash: data.content.hash });
1594
1633
  } else {
1595
1634
  const details = error?.details;
1596
- this._setTransactionState({ step: "error", ...buildData && { buildData }, ...details && { details } });
1635
+ this._setTransactionState({ step: "error", ...stateExtra, ...details && { details } });
1597
1636
  }
1598
1637
  } catch {
1599
- this._setTransactionState({ step: "error", ...buildData && { buildData } });
1638
+ this._setTransactionState({ step: "error", ...stateExtra });
1600
1639
  }
1601
1640
  }
1602
1641
  // ─── App config ───────────────────────────────────────────────────────────
@@ -1641,6 +1680,14 @@ var PollarClient = class {
1641
1680
  pollRampTransaction(txId, opts) {
1642
1681
  return pollRampTransaction(this._api, txId, opts);
1643
1682
  }
1683
+ _setTxHistoryState(next) {
1684
+ this._txHistoryState = next;
1685
+ for (const cb of this._txHistoryStateListeners) cb(next);
1686
+ }
1687
+ _setWalletBalanceState(next) {
1688
+ this._walletBalanceState = next;
1689
+ for (const cb of this._walletBalanceStateListeners) cb(next);
1690
+ }
1644
1691
  // ─── Private ──────────────────────────────────────────────────────────────
1645
1692
  /** Creates a new AbortController, cancelling any existing flow first. */
1646
1693
  _newController() {
@@ -1656,8 +1703,9 @@ var PollarClient = class {
1656
1703
  setAuthState: this._setAuthState.bind(this),
1657
1704
  storeSession: this._storeSession.bind(this),
1658
1705
  clearSession: this._clearSession.bind(this),
1659
- storeWalletAdapter: (adapter) => {
1706
+ storeWalletAdapter: (adapter, type) => {
1660
1707
  this._walletAdapter = adapter;
1708
+ writeWalletType(type);
1661
1709
  }
1662
1710
  };
1663
1711
  }
@@ -1679,6 +1727,14 @@ var PollarClient = class {
1679
1727
  this._session = readStorage();
1680
1728
  if (this._session) {
1681
1729
  this._authState = { step: "authenticated", session: this._session };
1730
+ if (this._session.data?.providers?.wallet?.address) {
1731
+ const storedType = readWalletType();
1732
+ if (storedType === "freighter" /* FREIGHTER */) {
1733
+ this._walletAdapter = new FreighterAdapter();
1734
+ } else if (storedType === "albedo" /* ALBEDO */) {
1735
+ this._walletAdapter = new AlbedoAdapter();
1736
+ }
1737
+ }
1682
1738
  console.info("[PollarClient] Session restored from storage");
1683
1739
  } else {
1684
1740
  console.info("[PollarClient] No session in storage");