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