@accesly/react 1.1.2 → 1.2.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.js CHANGED
@@ -9,6 +9,7 @@ var AcceslyContext = createContext(null);
9
9
  var ENVIRONMENT_DEFAULTS = {
10
10
  dev: {
11
11
  apiUrl: "https://3fki7eiio5.execute-api.us-east-1.amazonaws.com/dev",
12
+ walletStreamUrl: "https://ajlmn37thw7fxen3oyykbfmlrm0eecue.lambda-url.us-east-1.on.aws/",
12
13
  cognito: {
13
14
  region: "us-east-1",
14
15
  userPoolId: "us-east-1_K2Nag1tB1",
@@ -26,6 +27,7 @@ var ENVIRONMENT_DEFAULTS = {
26
27
  },
27
28
  staging: {
28
29
  apiUrl: "https://api-staging.accesly.xyz",
30
+ walletStreamUrl: "",
29
31
  cognito: {
30
32
  region: "us-east-1",
31
33
  userPoolId: "TBD-staging",
@@ -41,6 +43,7 @@ var ENVIRONMENT_DEFAULTS = {
41
43
  },
42
44
  prod: {
43
45
  apiUrl: "https://api.accesly.xyz",
46
+ walletStreamUrl: "",
44
47
  cognito: {
45
48
  region: "us-east-1",
46
49
  userPoolId: "TBD-prod",
@@ -926,8 +929,133 @@ function base64ToBytes(s) {
926
929
  for (let i = 0; i < bin.length; i += 1) arr[i] = bin.charCodeAt(i);
927
930
  return arr;
928
931
  }
932
+
933
+ // src/hooks/walletSubscription.ts
934
+ var ACTIVITY_BUFFER_MAX = 50;
935
+ var subscriptions = /* @__PURE__ */ new Map();
936
+ function buildSubscriptionUrl(streamUrl, walletAddress) {
937
+ const base = streamUrl.replace(/\/$/, "");
938
+ return `${base}/?walletAddress=${encodeURIComponent(walletAddress)}`;
939
+ }
940
+ function openConnection(state) {
941
+ if (state.eventSource) return;
942
+ if (typeof EventSource === "undefined") return;
943
+ let es;
944
+ try {
945
+ es = new EventSource(state.url, { withCredentials: false });
946
+ } catch (err) {
947
+ console.warn("[walletSubscription] EventSource construction failed", err);
948
+ return;
949
+ }
950
+ state.eventSource = es;
951
+ es.addEventListener("status", (ev) => {
952
+ try {
953
+ const data = JSON.parse(ev.data);
954
+ state.lastStatus = data;
955
+ for (const listener of state.listeners.status) listener(data);
956
+ } catch {
957
+ }
958
+ });
959
+ es.addEventListener("balance", (ev) => {
960
+ try {
961
+ const data = JSON.parse(ev.data);
962
+ state.lastBalance = data;
963
+ for (const listener of state.listeners.balance) listener(data);
964
+ } catch {
965
+ }
966
+ });
967
+ es.addEventListener("activity", (ev) => {
968
+ try {
969
+ const data = JSON.parse(ev.data);
970
+ const merged = [...data.events, ...state.activityBuffer];
971
+ const seen = /* @__PURE__ */ new Set();
972
+ const deduped = [];
973
+ for (const item of merged) {
974
+ const key = `${item.txHash}:${item.ledger}`;
975
+ if (seen.has(key)) continue;
976
+ seen.add(key);
977
+ deduped.push(item);
978
+ if (deduped.length >= ACTIVITY_BUFFER_MAX) break;
979
+ }
980
+ state.activityBuffer = deduped;
981
+ for (const listener of state.listeners.activity) {
982
+ listener({ events: state.activityBuffer });
983
+ }
984
+ } catch {
985
+ }
986
+ });
987
+ es.addEventListener("close", () => {
988
+ });
989
+ es.onerror = () => {
990
+ };
991
+ }
992
+ function closeConnection(state) {
993
+ if (!state.eventSource) return;
994
+ state.eventSource.close();
995
+ state.eventSource = null;
996
+ }
997
+ function getOrCreateSubscription(streamUrl, walletAddress) {
998
+ const existing = subscriptions.get(walletAddress);
999
+ if (existing) return existing;
1000
+ const state = {
1001
+ walletAddress,
1002
+ url: buildSubscriptionUrl(streamUrl, walletAddress),
1003
+ eventSource: null,
1004
+ listeners: {
1005
+ status: /* @__PURE__ */ new Set(),
1006
+ balance: /* @__PURE__ */ new Set(),
1007
+ activity: /* @__PURE__ */ new Set()
1008
+ },
1009
+ lastStatus: null,
1010
+ lastBalance: null,
1011
+ activityBuffer: [],
1012
+ refCount: 0
1013
+ };
1014
+ subscriptions.set(walletAddress, state);
1015
+ return state;
1016
+ }
1017
+ function subscribeToWalletEvent(streamUrl, walletAddress, eventType, listener) {
1018
+ if (!streamUrl || typeof EventSource === "undefined") return null;
1019
+ const state = getOrCreateSubscription(streamUrl, walletAddress);
1020
+ state.refCount += 1;
1021
+ state.listeners[eventType].add(listener);
1022
+ if (eventType === "status" && state.lastStatus) {
1023
+ listener(state.lastStatus);
1024
+ } else if (eventType === "balance" && state.lastBalance) {
1025
+ listener(state.lastBalance);
1026
+ } else if (eventType === "activity" && state.activityBuffer.length > 0) {
1027
+ listener({
1028
+ events: state.activityBuffer
1029
+ });
1030
+ }
1031
+ if (!state.eventSource) openConnection(state);
1032
+ return () => {
1033
+ state.listeners[eventType].delete(listener);
1034
+ state.refCount -= 1;
1035
+ if (state.refCount <= 0) {
1036
+ closeConnection(state);
1037
+ subscriptions.delete(walletAddress);
1038
+ }
1039
+ };
1040
+ }
1041
+ function closeAllWalletSubscriptions() {
1042
+ for (const state of subscriptions.values()) closeConnection(state);
1043
+ subscriptions.clear();
1044
+ }
1045
+
1046
+ // src/hooks/useWalletStatus.ts
929
1047
  var POLL_BACKOFF_MS = [2e3, 5e3, 1e4, 2e4, 3e4];
930
1048
  var STALE_THRESHOLD_MS = 6e4;
1049
+ function useStableRef(value) {
1050
+ const ref = useRef(value);
1051
+ ref.current = value;
1052
+ return ref;
1053
+ }
1054
+ function deriveStatus(onChain) {
1055
+ if (onChain === true) return "on-chain";
1056
+ if (onChain === false) return "pending-deploy";
1057
+ return "unknown";
1058
+ }
931
1059
  function useWalletStatus() {
932
1060
  const { wallet, _internal } = useAccesly();
933
1061
  const username = _internal.username;
@@ -936,147 +1064,75 @@ function useWalletStatus() {
936
1064
  const [onChain, setOnChain] = useState(null);
937
1065
  const [lastSuccessAt, setLastSuccessAt] = useState(0);
938
1066
  const [isStale, setIsStale] = useState(false);
939
- const refreshRef = useRef(() => Promise.resolve());
940
- const apply = useCallback((res) => {
941
- if (res.kind === "not-found") {
942
- setStatus("no-wallet");
943
- setWalletAddress(null);
944
- setOnChain(null);
945
- setLastSuccessAt(Date.now());
946
- setIsStale(false);
947
- return "no-wallet";
948
- }
949
- const next = res.onChain === true ? "on-chain" : res.onChain === false ? "pending-deploy" : "unknown";
950
- setStatus(next);
951
- setWalletAddress(res.walletAddress);
952
- setOnChain(res.onChain);
953
- setLastSuccessAt(Date.now());
954
- setIsStale(false);
955
- return next;
956
- }, []);
1067
+ const envDefaults = ENVIRONMENT_DEFAULTS[_internal.env];
1068
+ const streamUrl = envDefaults.walletStreamUrl;
1069
+ const walletRef = useStableRef(wallet);
957
1070
  const doFetch = useCallback(async () => {
958
1071
  if (!username) return null;
959
1072
  try {
960
- const remote = await wallet.fetchRemote();
961
- if (!remote) return apply({ kind: "not-found" });
962
- return apply({
963
- kind: "ok",
964
- walletAddress: remote.walletAddress,
965
- onChain: remote.onChain
966
- });
1073
+ const remote = await walletRef.current.fetchRemote();
1074
+ if (!remote) {
1075
+ setStatus("no-wallet");
1076
+ setWalletAddress(null);
1077
+ setOnChain(null);
1078
+ setLastSuccessAt(Date.now());
1079
+ setIsStale(false);
1080
+ return "no-wallet";
1081
+ }
1082
+ const next = deriveStatus(remote.onChain);
1083
+ setStatus(next);
1084
+ setWalletAddress(remote.walletAddress);
1085
+ setOnChain(remote.onChain);
1086
+ setLastSuccessAt(Date.now());
1087
+ setIsStale(false);
1088
+ return next;
967
1089
  } catch {
968
1090
  return null;
969
1091
  }
970
- }, [username, wallet, apply]);
971
- useEffect(() => {
972
- if (!username || typeof BroadcastChannel === "undefined") return void 0;
973
- const channel = new BroadcastChannel(`accesly:wallet:${username}`);
974
- channel.onmessage = (ev) => {
975
- const data = ev.data;
976
- if (data && (data.kind === "ok" || data.kind === "not-found")) {
977
- apply(data);
978
- }
979
- };
980
- return () => channel.close();
981
- }, [username, apply]);
982
- const broadcastIfAvailable = useCallback(
983
- (res) => {
984
- if (!username || typeof BroadcastChannel === "undefined") return;
985
- try {
986
- const channel = new BroadcastChannel(`accesly:wallet:${username}`);
987
- channel.postMessage(res);
988
- channel.close();
989
- } catch {
990
- }
991
- },
992
- [username]
993
- );
1092
+ }, [username, walletRef]);
1093
+ const doFetchRef = useStableRef(doFetch);
994
1094
  useEffect(() => {
995
1095
  if (!username) {
996
1096
  setStatus("unknown");
997
1097
  return void 0;
998
1098
  }
999
1099
  let cancelled = false;
1100
+ let unsubscribe = null;
1000
1101
  let pollTimer = null;
1001
1102
  let backoffIndex = 0;
1002
- let eventSource = null;
1003
1103
  const schedulePoll = (delayMs) => {
1004
1104
  if (cancelled) return;
1005
1105
  pollTimer = setTimeout(async () => {
1006
1106
  if (cancelled) return;
1007
- if (typeof document !== "undefined" && document.hidden) {
1008
- return;
1009
- }
1010
- const next = await doFetch();
1011
- if (next !== null) {
1012
- broadcastIfAvailable({
1013
- kind: next === "no-wallet" ? "not-found" : "ok",
1014
- walletAddress: walletAddress ?? "",
1015
- onChain
1016
- });
1017
- }
1018
- if (next !== "on-chain" && next !== "no-wallet") {
1019
- backoffIndex = Math.min(backoffIndex + 1, POLL_BACKOFF_MS.length - 1);
1020
- schedulePoll(POLL_BACKOFF_MS[backoffIndex]);
1021
- }
1107
+ if (typeof document !== "undefined" && document.hidden) return;
1108
+ const next = await doFetchRef.current();
1109
+ if (next === "on-chain" || next === "no-wallet") return;
1110
+ backoffIndex = Math.min(backoffIndex + 1, POLL_BACKOFF_MS.length - 1);
1111
+ schedulePoll(POLL_BACKOFF_MS[backoffIndex]);
1022
1112
  }, delayMs);
1023
1113
  };
1024
- const startPolling = () => {
1025
- backoffIndex = 0;
1026
- schedulePoll(POLL_BACKOFF_MS[0]);
1027
- };
1028
- const stopPolling = () => {
1029
- if (pollTimer) {
1030
- clearTimeout(pollTimer);
1031
- pollTimer = null;
1032
- }
1033
- };
1034
- const tryOpenSse = () => {
1035
- if (typeof EventSource === "undefined") return false;
1036
- try {
1037
- const url = `${_internal.apiUrl.replace(/\/$/, "")}/wallets/stream`;
1038
- eventSource = new EventSource(url, { withCredentials: false });
1039
- eventSource.onmessage = (ev) => {
1040
- try {
1041
- const data = JSON.parse(ev.data);
1042
- if (typeof data.walletAddress === "string") {
1043
- const res = {
1044
- kind: "ok",
1045
- walletAddress: data.walletAddress,
1046
- onChain: data.onChain ?? null
1047
- };
1048
- apply(res);
1049
- broadcastIfAvailable(res);
1050
- }
1051
- } catch {
1052
- }
1053
- };
1054
- eventSource.onerror = () => {
1055
- eventSource?.close();
1056
- eventSource = null;
1057
- startPolling();
1058
- };
1059
- return true;
1060
- } catch {
1061
- return false;
1062
- }
1063
- };
1064
1114
  void (async () => {
1065
- const next = await doFetch();
1115
+ const initial = await doFetchRef.current();
1066
1116
  if (cancelled) return;
1067
- if (next === "on-chain" || next === "no-wallet") {
1068
- return;
1117
+ if (initial === "on-chain" || initial === "no-wallet") return;
1118
+ if (walletAddress) {
1119
+ unsubscribe = subscribeToWalletEvent(streamUrl, walletAddress, "status", (data) => {
1120
+ setWalletAddress(data.walletAddress);
1121
+ setOnChain(data.onChain);
1122
+ setStatus(deriveStatus(data.onChain));
1123
+ setLastSuccessAt(Date.now());
1124
+ setIsStale(false);
1125
+ });
1126
+ }
1127
+ if (!unsubscribe) {
1128
+ backoffIndex = 0;
1129
+ schedulePoll(POLL_BACKOFF_MS[0]);
1069
1130
  }
1070
- const sseOpen = tryOpenSse();
1071
- if (!sseOpen) startPolling();
1072
1131
  })();
1073
1132
  const onVisibilityChange = () => {
1074
1133
  if (typeof document === "undefined") return;
1075
- if (document.hidden) {
1076
- stopPolling();
1077
- } else if (!eventSource && status !== "on-chain" && status !== "no-wallet") {
1078
- void doFetch();
1079
- startPolling();
1134
+ if (!document.hidden && !unsubscribe) {
1135
+ void doFetchRef.current();
1080
1136
  }
1081
1137
  };
1082
1138
  if (typeof document !== "undefined") {
@@ -1087,35 +1143,25 @@ function useWalletStatus() {
1087
1143
  setIsStale(true);
1088
1144
  }
1089
1145
  }, 3e4);
1090
- refreshRef.current = async () => {
1091
- const next = await doFetch();
1092
- if (next === "on-chain" || next === "no-wallet") {
1093
- stopPolling();
1094
- } else {
1095
- backoffIndex = 0;
1096
- stopPolling();
1097
- startPolling();
1098
- }
1099
- };
1100
1146
  return () => {
1101
1147
  cancelled = true;
1102
- stopPolling();
1148
+ if (unsubscribe) unsubscribe();
1149
+ if (pollTimer) clearTimeout(pollTimer);
1103
1150
  clearInterval(staleTimer);
1104
- eventSource?.close();
1105
1151
  if (typeof document !== "undefined") {
1106
1152
  document.removeEventListener("visibilitychange", onVisibilityChange);
1107
1153
  }
1108
1154
  };
1109
- }, [username, _internal.apiUrl, doFetch, apply, broadcastIfAvailable]);
1155
+ }, [username, streamUrl, walletAddress]);
1110
1156
  const refresh = useCallback(async () => {
1111
- await refreshRef.current();
1112
- }, []);
1157
+ await doFetchRef.current();
1158
+ }, [doFetchRef]);
1113
1159
  return { status, walletAddress, onChain, isStale, refresh };
1114
1160
  }
1115
- var POLL_INTERVAL_MS = 8e3;
1116
- function useStableRef(fn) {
1117
- const ref = useRef(fn);
1118
- ref.current = fn;
1161
+ var POLL_FALLBACK_MS = 1e4;
1162
+ function useStableRef2(value) {
1163
+ const ref = useRef(value);
1164
+ ref.current = value;
1119
1165
  return ref;
1120
1166
  }
1121
1167
  function useBalance(walletAddress) {
@@ -1128,8 +1174,7 @@ function useBalance(walletAddress) {
1128
1174
  const [xlm, setXlm] = useState(null);
1129
1175
  const [isLoading, setIsLoading] = useState(true);
1130
1176
  const [error, setError] = useState(null);
1131
- const fetchInFlight = useRef(false);
1132
- const walletRef = useStableRef(wallet);
1177
+ const walletRef = useStableRef2(wallet);
1133
1178
  useEffect(() => {
1134
1179
  if (walletAddress) {
1135
1180
  setResolvedAddress(walletAddress);
@@ -1153,11 +1198,11 @@ function useBalance(walletAddress) {
1153
1198
  cancelled = true;
1154
1199
  };
1155
1200
  }, [walletAddress, username, walletRef]);
1156
- const endpointsRef = useStableRef(_internal.endpoints);
1157
- const doFetch = useCallback(async () => {
1201
+ const envDefaults = ENVIRONMENT_DEFAULTS[_internal.env];
1202
+ const streamUrl = envDefaults.walletStreamUrl;
1203
+ const endpointsRef = useStableRef2(_internal.endpoints);
1204
+ const doFetchOnce = useCallback(async () => {
1158
1205
  if (!resolvedAddress) return;
1159
- if (fetchInFlight.current) return;
1160
- fetchInFlight.current = true;
1161
1206
  try {
1162
1207
  const res = await endpointsRef.current.walletBalance(resolvedAddress);
1163
1208
  setStroops(res.xlm.stroops);
@@ -1167,60 +1212,58 @@ function useBalance(walletAddress) {
1167
1212
  setError(err);
1168
1213
  } finally {
1169
1214
  setIsLoading(false);
1170
- fetchInFlight.current = false;
1171
1215
  }
1172
1216
  }, [resolvedAddress, endpointsRef]);
1173
- const doFetchRef = useStableRef(doFetch);
1217
+ const doFetchRef = useStableRef2(doFetchOnce);
1174
1218
  useEffect(() => {
1175
1219
  if (!resolvedAddress) {
1176
1220
  setIsLoading(false);
1177
1221
  return void 0;
1178
1222
  }
1179
- void doFetchRef.current();
1180
- let interval = null;
1181
- const startInterval = () => {
1182
- if (interval) return;
1183
- interval = setInterval(() => {
1184
- if (typeof document !== "undefined" && document.hidden) return;
1185
- void doFetchRef.current();
1186
- }, POLL_INTERVAL_MS);
1187
- };
1188
- const stopInterval = () => {
1189
- if (interval) {
1190
- clearInterval(interval);
1191
- interval = null;
1223
+ const unsubscribe = subscribeToWalletEvent(
1224
+ streamUrl,
1225
+ resolvedAddress,
1226
+ "balance",
1227
+ (data) => {
1228
+ setStroops(data.stroops);
1229
+ setXlm(data.xlm);
1230
+ setError(null);
1231
+ setIsLoading(false);
1192
1232
  }
1193
- };
1194
- startInterval();
1233
+ );
1234
+ if (unsubscribe) {
1235
+ void doFetchRef.current();
1236
+ return unsubscribe;
1237
+ }
1238
+ void doFetchRef.current();
1239
+ const interval = setInterval(() => {
1240
+ if (typeof document !== "undefined" && document.hidden) return;
1241
+ void doFetchRef.current();
1242
+ }, POLL_FALLBACK_MS);
1195
1243
  const onVisibilityChange = () => {
1196
1244
  if (typeof document === "undefined") return;
1197
- if (document.hidden) {
1198
- stopInterval();
1199
- } else {
1200
- void doFetchRef.current();
1201
- startInterval();
1202
- }
1245
+ if (!document.hidden) void doFetchRef.current();
1203
1246
  };
1204
1247
  if (typeof document !== "undefined") {
1205
1248
  document.addEventListener("visibilitychange", onVisibilityChange);
1206
1249
  }
1207
1250
  return () => {
1208
- stopInterval();
1251
+ clearInterval(interval);
1209
1252
  if (typeof document !== "undefined") {
1210
1253
  document.removeEventListener("visibilitychange", onVisibilityChange);
1211
1254
  }
1212
1255
  };
1213
- }, [resolvedAddress, doFetchRef]);
1256
+ }, [resolvedAddress, streamUrl, doFetchRef]);
1214
1257
  const refresh = useCallback(async () => {
1215
1258
  await doFetchRef.current();
1216
1259
  }, [doFetchRef]);
1217
1260
  return { stroops, xlm, isLoading, error, refresh };
1218
1261
  }
1219
- var POLL_INTERVAL_MS2 = 2e4;
1262
+ var POLL_FALLBACK_MS2 = 25e3;
1220
1263
  var DEFAULT_LIMIT = 20;
1221
- function useStableRef2(fn) {
1222
- const ref = useRef(fn);
1223
- ref.current = fn;
1264
+ function useStableRef3(value) {
1265
+ const ref = useRef(value);
1266
+ ref.current = value;
1224
1267
  return ref;
1225
1268
  }
1226
1269
  function useWalletActivity(walletAddress, opts = {}) {
@@ -1233,8 +1276,7 @@ function useWalletActivity(walletAddress, opts = {}) {
1233
1276
  const [events, setEvents] = useState([]);
1234
1277
  const [isLoading, setIsLoading] = useState(true);
1235
1278
  const [error, setError] = useState(null);
1236
- const fetchInFlight = useRef(false);
1237
- const walletRef = useStableRef2(wallet);
1279
+ const walletRef = useStableRef3(wallet);
1238
1280
  useEffect(() => {
1239
1281
  if (walletAddress) {
1240
1282
  setResolvedAddress(walletAddress);
@@ -1258,71 +1300,76 @@ function useWalletActivity(walletAddress, opts = {}) {
1258
1300
  cancelled = true;
1259
1301
  };
1260
1302
  }, [walletAddress, username, walletRef]);
1261
- const endpointsRef = useStableRef2(_internal.endpoints);
1262
- const doFetch = useCallback(async () => {
1303
+ const envDefaults = ENVIRONMENT_DEFAULTS[_internal.env];
1304
+ const streamUrl = envDefaults.walletStreamUrl;
1305
+ const endpointsRef = useStableRef3(_internal.endpoints);
1306
+ const doFetchOnce = useCallback(async () => {
1263
1307
  if (!resolvedAddress) return;
1264
- if (fetchInFlight.current) return;
1265
- fetchInFlight.current = true;
1266
1308
  try {
1267
1309
  const res = await endpointsRef.current.walletActivity(resolvedAddress, limit);
1268
- setEvents(res.events);
1310
+ const adapted = [];
1311
+ for (const ev of res.events) {
1312
+ const conv = adaptRestEvent(ev);
1313
+ if (conv) adapted.push(conv);
1314
+ }
1315
+ setEvents(adapted.slice(0, limit));
1269
1316
  setError(null);
1270
1317
  } catch (err) {
1271
1318
  setError(err);
1272
1319
  } finally {
1273
1320
  setIsLoading(false);
1274
- fetchInFlight.current = false;
1275
1321
  }
1276
1322
  }, [resolvedAddress, limit, endpointsRef]);
1277
- const doFetchRef = useStableRef2(doFetch);
1323
+ const doFetchRef = useStableRef3(doFetchOnce);
1278
1324
  useEffect(() => {
1279
1325
  if (!resolvedAddress) {
1280
1326
  setIsLoading(false);
1281
1327
  return void 0;
1282
1328
  }
1283
- void doFetchRef.current();
1284
- let interval = null;
1285
- const start = () => {
1286
- if (interval) return;
1287
- interval = setInterval(() => {
1288
- if (typeof document !== "undefined" && document.hidden) return;
1289
- void doFetchRef.current();
1290
- }, POLL_INTERVAL_MS2);
1291
- };
1292
- const stop = () => {
1293
- if (interval) {
1294
- clearInterval(interval);
1295
- interval = null;
1296
- }
1297
- };
1298
- start();
1299
- const onVisibilityChange = () => {
1300
- if (typeof document === "undefined") return;
1301
- if (document.hidden) stop();
1302
- else {
1303
- void doFetchRef.current();
1304
- start();
1329
+ const unsubscribe = subscribeToWalletEvent(
1330
+ streamUrl,
1331
+ resolvedAddress,
1332
+ "activity",
1333
+ (data) => {
1334
+ setEvents(data.events.slice(0, limit));
1335
+ setError(null);
1336
+ setIsLoading(false);
1305
1337
  }
1306
- };
1307
- if (typeof document !== "undefined") {
1308
- document.addEventListener("visibilitychange", onVisibilityChange);
1338
+ );
1339
+ if (unsubscribe) {
1340
+ void doFetchRef.current();
1341
+ return unsubscribe;
1309
1342
  }
1310
- return () => {
1311
- stop();
1312
- if (typeof document !== "undefined") {
1313
- document.removeEventListener("visibilitychange", onVisibilityChange);
1314
- }
1315
- };
1316
- }, [resolvedAddress, doFetchRef]);
1343
+ void doFetchRef.current();
1344
+ const interval = setInterval(() => {
1345
+ if (typeof document !== "undefined" && document.hidden) return;
1346
+ void doFetchRef.current();
1347
+ }, POLL_FALLBACK_MS2);
1348
+ return () => clearInterval(interval);
1349
+ }, [resolvedAddress, streamUrl, limit, doFetchRef]);
1317
1350
  const refresh = useCallback(async () => {
1318
1351
  await doFetchRef.current();
1319
1352
  }, [doFetchRef]);
1320
1353
  return { events, isLoading, error, refresh };
1321
1354
  }
1355
+ function adaptRestEvent(ev) {
1356
+ const t0 = ev.topics[0];
1357
+ if (typeof t0 !== "string") return null;
1358
+ if (t0 === "SignerRotated") {
1359
+ return {
1360
+ type: "signer-rotated",
1361
+ txHash: ev.txHash,
1362
+ ledger: ev.ledger,
1363
+ timestamp: ev.timestamp,
1364
+ newOwnerEd25519Hex: typeof ev.value === "string" ? ev.value : ""
1365
+ };
1366
+ }
1367
+ return null;
1368
+ }
1322
1369
 
1323
1370
  // src/index.ts
1324
1371
  var REACT_ADAPTER_VERSION = "0.0.0";
1325
1372
 
1326
- export { AcceslyContext, AcceslyProvider, ENVIRONMENT_DEFAULTS, NotImplementedYetError, REACT_ADAPTER_VERSION, useAccesly, useBalance, useWalletActivity, useWalletStatus };
1373
+ export { AcceslyContext, AcceslyProvider, ENVIRONMENT_DEFAULTS, NotImplementedYetError, REACT_ADAPTER_VERSION, closeAllWalletSubscriptions, subscribeToWalletEvent, useAccesly, useBalance, useWalletActivity, useWalletStatus };
1327
1374
  //# sourceMappingURL=index.js.map
1328
1375
  //# sourceMappingURL=index.js.map