@dexterai/x402 1.5.2 → 1.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.
@@ -1066,13 +1066,43 @@ function useAccessPass(config) {
1066
1066
  autoConnect = true,
1067
1067
  verbose = false
1068
1068
  } = config;
1069
+ const storageKey = `x402-access-pass:${resourceUrl}`;
1070
+ function loadPersistedPass() {
1071
+ if (typeof sessionStorage === "undefined") return null;
1072
+ try {
1073
+ const stored = sessionStorage.getItem(storageKey);
1074
+ if (!stored) return null;
1075
+ const parsed = JSON.parse(stored);
1076
+ if (new Date(parsed.expiresAt).getTime() <= Date.now()) {
1077
+ sessionStorage.removeItem(storageKey);
1078
+ return null;
1079
+ }
1080
+ return parsed;
1081
+ } catch {
1082
+ return null;
1083
+ }
1084
+ }
1085
+ function persistPass(jwt, tier, expiresAt) {
1086
+ if (typeof sessionStorage === "undefined") return;
1087
+ try {
1088
+ sessionStorage.setItem(storageKey, JSON.stringify({ jwt, tier, expiresAt }));
1089
+ } catch {
1090
+ }
1091
+ }
1092
+ const persisted = loadPersistedPass();
1069
1093
  const [tiers, setTiers] = (0, import_react2.useState)(null);
1070
1094
  const [customRatePerHour, setCustomRatePerHour] = (0, import_react2.useState)(null);
1071
1095
  const [isLoadingTiers, setIsLoadingTiers] = (0, import_react2.useState)(false);
1072
- const [passJwt, setPassJwt] = (0, import_react2.useState)(null);
1073
- const [passInfo, setPassInfo] = (0, import_react2.useState)(null);
1096
+ const [passJwt, setPassJwt] = (0, import_react2.useState)(persisted?.jwt || null);
1097
+ const [passInfo, setPassInfo] = (0, import_react2.useState)(
1098
+ persisted ? { tier: persisted.tier, expiresAt: persisted.expiresAt } : null
1099
+ );
1074
1100
  const [isPurchasing, setIsPurchasing] = (0, import_react2.useState)(false);
1075
1101
  const [purchaseError, setPurchaseError] = (0, import_react2.useState)(null);
1102
+ const passJwtRef = (0, import_react2.useRef)(passJwt);
1103
+ (0, import_react2.useEffect)(() => {
1104
+ passJwtRef.current = passJwt;
1105
+ }, [passJwt]);
1076
1106
  const log = (0, import_react2.useCallback)((...args) => {
1077
1107
  if (verbose) console.log("[useAccessPass]", ...args);
1078
1108
  }, [verbose]);
@@ -1139,27 +1169,31 @@ function useAccessPass(config) {
1139
1169
  else if (durationSeconds) url += (url.includes("?") ? "&" : "?") + `duration=${durationSeconds}`;
1140
1170
  const res = await client.fetch(url, { method: "POST" });
1141
1171
  const jwt = res.headers.get("ACCESS-PASS");
1142
- log("ACCESS-PASS header:", jwt ? `found (${jwt.slice(0, 20)}...)` : "NOT FOUND");
1143
- log("Response status:", res.status, "headers:", [...res.headers.entries()].map(([k, v]) => `${k}: ${v.slice(0, 30)}`).join(", "));
1172
+ log("ACCESS-PASS header:", jwt ? "found" : "NOT FOUND");
1144
1173
  if (jwt) {
1145
1174
  setPassJwt(jwt);
1175
+ let passTier = tier || "unknown";
1176
+ let passExpiresAt = "";
1146
1177
  try {
1147
1178
  const body = await res.json();
1148
- setPassInfo({
1149
- tier: body.accessPass?.tier || tier || "unknown",
1150
- expiresAt: body.accessPass?.expiresAt || ""
1151
- });
1179
+ passTier = body.accessPass?.tier || passTier;
1180
+ passExpiresAt = body.accessPass?.expiresAt || "";
1152
1181
  } catch {
1153
- const parts = jwt.split(".");
1154
- if (parts.length === 3) {
1155
- const payload = JSON.parse(atob(parts[1].replace(/-/g, "+").replace(/_/g, "/")));
1156
- setPassInfo({
1157
- tier: payload.tier || tier || "unknown",
1158
- expiresAt: new Date(payload.exp * 1e3).toISOString()
1159
- });
1182
+ }
1183
+ if (!passExpiresAt) {
1184
+ try {
1185
+ const parts = jwt.split(".");
1186
+ if (parts.length === 3) {
1187
+ const payload = JSON.parse(atob(parts[1].replace(/-/g, "+").replace(/_/g, "/")));
1188
+ passTier = payload.tier || passTier;
1189
+ passExpiresAt = new Date(payload.exp * 1e3).toISOString();
1190
+ }
1191
+ } catch {
1160
1192
  }
1161
1193
  }
1162
- log("Pass purchased:", tier);
1194
+ setPassInfo({ tier: passTier, expiresAt: passExpiresAt });
1195
+ persistPass(jwt, passTier, passExpiresAt);
1196
+ log("Pass purchased and persisted:", passTier, passExpiresAt);
1163
1197
  }
1164
1198
  } catch (err) {
1165
1199
  const error = err instanceof Error ? err : new Error(String(err));
@@ -1171,17 +1205,33 @@ function useAccessPass(config) {
1171
1205
  }, [resourceUrl, client, log]);
1172
1206
  const fetchWithPass = (0, import_react2.useCallback)(async (path, init) => {
1173
1207
  const url = path.startsWith("http") ? path : `${resourceUrl.replace(/\/$/, "")}${path.startsWith("/") ? "" : "/"}${path}`;
1174
- if (isPassValid && pass) {
1175
- return fetch(url, {
1176
- ...init,
1177
- headers: {
1178
- ...init?.headers || {},
1179
- "Authorization": `Bearer ${pass.jwt}`
1208
+ const currentJwt = passJwtRef.current;
1209
+ if (currentJwt) {
1210
+ try {
1211
+ const parts = currentJwt.split(".");
1212
+ if (parts.length === 3) {
1213
+ const payload = JSON.parse(atob(parts[1].replace(/-/g, "+").replace(/_/g, "/")));
1214
+ if (payload.exp && payload.exp > Date.now() / 1e3) {
1215
+ return fetch(url, {
1216
+ ...init,
1217
+ headers: {
1218
+ ...init?.headers || {},
1219
+ "Authorization": `Bearer ${currentJwt}`
1220
+ }
1221
+ });
1222
+ }
1180
1223
  }
1181
- });
1224
+ } catch {
1225
+ }
1226
+ setPassJwt(null);
1227
+ setPassInfo(null);
1228
+ try {
1229
+ sessionStorage.removeItem(storageKey);
1230
+ } catch {
1231
+ }
1182
1232
  }
1183
1233
  return client.fetch(url, init);
1184
- }, [resourceUrl, isPassValid, pass, client]);
1234
+ }, [resourceUrl, client, storageKey]);
1185
1235
  return {
1186
1236
  tiers,
1187
1237
  customRatePerHour,