@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/.tsbuildinfo +1 -1
- package/dist/index.cjs +255 -206
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +116 -59
- package/dist/index.d.ts +116 -59
- package/dist/index.js +254 -207
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
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
|
|
940
|
-
const
|
|
941
|
-
|
|
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
|
|
961
|
-
if (!remote)
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
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,
|
|
971
|
-
|
|
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
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
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
|
|
1115
|
+
const initial = await doFetchRef.current();
|
|
1066
1116
|
if (cancelled) return;
|
|
1067
|
-
if (
|
|
1068
|
-
|
|
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
|
-
|
|
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,33 +1143,23 @@ 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
|
-
|
|
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,
|
|
1155
|
+
}, [username, streamUrl, walletAddress]);
|
|
1110
1156
|
const refresh = useCallback(async () => {
|
|
1111
|
-
await
|
|
1112
|
-
}, []);
|
|
1157
|
+
await doFetchRef.current();
|
|
1158
|
+
}, [doFetchRef]);
|
|
1113
1159
|
return { status, walletAddress, onChain, isStale, refresh };
|
|
1114
1160
|
}
|
|
1115
|
-
var
|
|
1116
|
-
function
|
|
1161
|
+
var POLL_FALLBACK_MS = 1e4;
|
|
1162
|
+
function useStableRef2(value) {
|
|
1117
1163
|
const ref = useRef(value);
|
|
1118
1164
|
ref.current = value;
|
|
1119
1165
|
return ref;
|
|
@@ -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
|
|
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
|
|
1157
|
-
const
|
|
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,58 +1212,56 @@ 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 =
|
|
1217
|
+
const doFetchRef = useStableRef2(doFetchOnce);
|
|
1174
1218
|
useEffect(() => {
|
|
1175
1219
|
if (!resolvedAddress) {
|
|
1176
1220
|
setIsLoading(false);
|
|
1177
1221
|
return void 0;
|
|
1178
1222
|
}
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
1262
|
+
var POLL_FALLBACK_MS2 = 25e3;
|
|
1220
1263
|
var DEFAULT_LIMIT = 20;
|
|
1221
|
-
function
|
|
1264
|
+
function useStableRef3(value) {
|
|
1222
1265
|
const ref = useRef(value);
|
|
1223
1266
|
ref.current = value;
|
|
1224
1267
|
return ref;
|
|
@@ -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
|
|
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
|
|
1262
|
-
const
|
|
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
|
-
|
|
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 =
|
|
1323
|
+
const doFetchRef = useStableRef3(doFetchOnce);
|
|
1278
1324
|
useEffect(() => {
|
|
1279
1325
|
if (!resolvedAddress) {
|
|
1280
1326
|
setIsLoading(false);
|
|
1281
1327
|
return void 0;
|
|
1282
1328
|
}
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
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 (
|
|
1308
|
-
|
|
1338
|
+
);
|
|
1339
|
+
if (unsubscribe) {
|
|
1340
|
+
void doFetchRef.current();
|
|
1341
|
+
return unsubscribe;
|
|
1309
1342
|
}
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
if (typeof document !== "undefined")
|
|
1313
|
-
|
|
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
|