@accesly/react 1.2.0 → 1.3.1

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
@@ -1,158 +1,350 @@
1
1
  'use strict';
2
2
 
3
- var core = require('@accesly/core');
4
3
  var react = require('react');
4
+ var core = require('@accesly/core');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
 
7
- // src/provider.tsx
8
- var AcceslyContext = react.createContext(null);
7
+ var __defProp = Object.defineProperty;
8
+ var __getOwnPropNames = Object.getOwnPropertyNames;
9
+ var __esm = (fn, res) => function __init() {
10
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
+ };
12
+ var __export = (target, all) => {
13
+ for (var name in all)
14
+ __defProp(target, name, { get: all[name], enumerable: true });
15
+ };
16
+ exports.AcceslyContext = void 0;
17
+ var init_context = __esm({
18
+ "src/context.ts"() {
19
+ exports.AcceslyContext = react.createContext(null);
20
+ }
21
+ });
9
22
 
10
23
  // src/config.ts
11
- var ENVIRONMENT_DEFAULTS = {
12
- dev: {
13
- apiUrl: "https://3fki7eiio5.execute-api.us-east-1.amazonaws.com/dev",
14
- walletStreamUrl: "https://ajlmn37thw7fxen3oyykbfmlrm0eecue.lambda-url.us-east-1.on.aws/",
15
- cognito: {
16
- region: "us-east-1",
17
- userPoolId: "us-east-1_K2Nag1tB1",
18
- userPoolClientId: "6r64diep7pne50sender4557jt"
19
- },
20
- stellar: {
21
- networkPassphrase: "Test SDF Network ; September 2015",
22
- horizonUrl: "https://horizon-testnet.stellar.org",
23
- sorobanRpcUrl: "https://soroban-testnet.stellar.org",
24
- // OZ Relayer channels-fund see CloudServices-accesly/docs/Deployed_Resources_dev.md
25
- deployerAddress: "GDRHSVLY3VCEHCHCSR5MZR2ALYLCERDDFT3ULCUIELGFVYHTZFCMNU4E",
26
- // accesly-contracts Phase 1 deploy on Stellar testnet.
27
- ed25519VerifierAddress: "CALVIIGIOMODZMWTMKZLSD4PZFFEPWQBSYERHUFM6MH5FLWKCHW4E4G5"
24
+ exports.ENVIRONMENT_DEFAULTS = void 0;
25
+ var init_config = __esm({
26
+ "src/config.ts"() {
27
+ exports.ENVIRONMENT_DEFAULTS = {
28
+ dev: {
29
+ apiUrl: "https://3fki7eiio5.execute-api.us-east-1.amazonaws.com/dev",
30
+ walletStreamUrl: "https://ajlmn37thw7fxen3oyykbfmlrm0eecue.lambda-url.us-east-1.on.aws/",
31
+ cognito: {
32
+ region: "us-east-1",
33
+ userPoolId: "us-east-1_K2Nag1tB1",
34
+ userPoolClientId: "6r64diep7pne50sender4557jt"
35
+ },
36
+ stellar: {
37
+ networkPassphrase: "Test SDF Network ; September 2015",
38
+ horizonUrl: "https://horizon-testnet.stellar.org",
39
+ sorobanRpcUrl: "https://soroban-testnet.stellar.org",
40
+ // OZ Relayer channels-fund — see CloudServices-accesly/docs/Deployed_Resources_dev.md
41
+ deployerAddress: "GDRHSVLY3VCEHCHCSR5MZR2ALYLCERDDFT3ULCUIELGFVYHTZFCMNU4E",
42
+ // accesly-contracts Phase 1 deploy on Stellar testnet.
43
+ ed25519VerifierAddress: "CALVIIGIOMODZMWTMKZLSD4PZFFEPWQBSYERHUFM6MH5FLWKCHW4E4G5"
44
+ }
45
+ },
46
+ staging: {
47
+ apiUrl: "https://api-staging.accesly.xyz",
48
+ walletStreamUrl: "",
49
+ cognito: {
50
+ region: "us-east-1",
51
+ userPoolId: "TBD-staging",
52
+ userPoolClientId: "TBD-staging"
53
+ },
54
+ stellar: {
55
+ networkPassphrase: "Test SDF Network ; September 2015",
56
+ horizonUrl: "https://horizon-testnet.stellar.org",
57
+ sorobanRpcUrl: "https://soroban-testnet.stellar.org",
58
+ deployerAddress: "GDRHSVLY3VCEHCHCSR5MZR2ALYLCERDDFT3ULCUIELGFVYHTZFCMNU4E",
59
+ ed25519VerifierAddress: "CALVIIGIOMODZMWTMKZLSD4PZFFEPWQBSYERHUFM6MH5FLWKCHW4E4G5"
60
+ }
61
+ },
62
+ prod: {
63
+ apiUrl: "https://api.accesly.xyz",
64
+ walletStreamUrl: "",
65
+ cognito: {
66
+ region: "us-east-1",
67
+ userPoolId: "TBD-prod",
68
+ userPoolClientId: "TBD-prod"
69
+ },
70
+ stellar: {
71
+ networkPassphrase: "Public Global Stellar Network ; September 2015",
72
+ horizonUrl: "https://horizon.stellar.org",
73
+ sorobanRpcUrl: "https://soroban-rpc.mainnet.stellar.org",
74
+ deployerAddress: "TBD-prod",
75
+ ed25519VerifierAddress: "TBD-prod"
76
+ }
77
+ }
78
+ };
79
+ }
80
+ });
81
+ function isSorobanDeployPendingError(err) {
82
+ if (!(err instanceof core.AccesslyApiError)) return false;
83
+ const haystack = `${err.message ?? ""} ${err.code ?? ""}`.toLowerCase();
84
+ return haystack.includes("txsorobaninvalid") || haystack.includes("soroban sendtransaction") || haystack.includes("soroban submit failed") || haystack.includes("scecexceededlimit") || haystack.includes("exceededlimit");
85
+ }
86
+ var init_sorobanDeployStatus = __esm({
87
+ "src/hooks/sorobanDeployStatus.ts"() {
88
+ }
89
+ });
90
+
91
+ // src/hooks/useWalletHistory.ts
92
+ var useWalletHistory_exports = {};
93
+ __export(useWalletHistory_exports, {
94
+ historyClearOptimistic: () => historyClearOptimistic,
95
+ historyOptimisticPush: () => historyOptimisticPush,
96
+ useWalletHistory: () => useWalletHistory
97
+ });
98
+ function useStableRef(value) {
99
+ const ref = react.useRef(value);
100
+ ref.current = value;
101
+ return ref;
102
+ }
103
+ function loadCache(walletAddress) {
104
+ if (typeof localStorage === "undefined") return null;
105
+ try {
106
+ const raw = localStorage.getItem(CACHE_KEY_PREFIX + walletAddress);
107
+ if (!raw) return null;
108
+ const parsed = JSON.parse(raw);
109
+ if (Date.now() - parsed.storedAt > CACHE_TTL_MS) return null;
110
+ return parsed;
111
+ } catch {
112
+ return null;
113
+ }
114
+ }
115
+ function saveCache(walletAddress, entry) {
116
+ if (typeof localStorage === "undefined") return;
117
+ try {
118
+ localStorage.setItem(CACHE_KEY_PREFIX + walletAddress, JSON.stringify(entry));
119
+ } catch {
120
+ }
121
+ }
122
+ function historyOptimisticPush(walletAddress, item) {
123
+ const current = optimisticItems.get(walletAddress) ?? [];
124
+ optimisticItems.set(walletAddress, [item, ...current]);
125
+ const listeners = optimisticListeners.get(walletAddress);
126
+ if (listeners) {
127
+ for (const fn of listeners) fn(optimisticItems.get(walletAddress) ?? []);
128
+ }
129
+ }
130
+ function historyClearOptimistic(walletAddress) {
131
+ optimisticItems.delete(walletAddress);
132
+ const listeners = optimisticListeners.get(walletAddress);
133
+ if (listeners) {
134
+ for (const fn of listeners) fn([]);
135
+ }
136
+ }
137
+ function subscribeOptimistic(walletAddress, listener) {
138
+ let set = optimisticListeners.get(walletAddress);
139
+ if (!set) {
140
+ set = /* @__PURE__ */ new Set();
141
+ optimisticListeners.set(walletAddress, set);
142
+ }
143
+ set.add(listener);
144
+ return () => {
145
+ set?.delete(listener);
146
+ if (set && set.size === 0) optimisticListeners.delete(walletAddress);
147
+ };
148
+ }
149
+ function useWalletHistory(walletAddress, opts = {}) {
150
+ const { wallet, _internal } = useAccesly();
151
+ const username = _internal.username;
152
+ const [resolvedAddress, setResolvedAddress] = react.useState(walletAddress ?? null);
153
+ const [events, setEvents] = react.useState([]);
154
+ const [optimistic, setOptimistic] = react.useState([]);
155
+ const [cursors, setCursors] = react.useState({ smartAccount: null, transfers: null });
156
+ const [isLoading, setIsLoading] = react.useState(true);
157
+ const [error, setError] = react.useState(null);
158
+ const [hasMore, setHasMore] = react.useState(true);
159
+ const walletRef = useStableRef(wallet);
160
+ react.useEffect(() => {
161
+ if (walletAddress) {
162
+ setResolvedAddress(walletAddress);
163
+ return;
28
164
  }
29
- },
30
- staging: {
31
- apiUrl: "https://api-staging.accesly.xyz",
32
- walletStreamUrl: "",
33
- cognito: {
34
- region: "us-east-1",
35
- userPoolId: "TBD-staging",
36
- userPoolClientId: "TBD-staging"
37
- },
38
- stellar: {
39
- networkPassphrase: "Test SDF Network ; September 2015",
40
- horizonUrl: "https://horizon-testnet.stellar.org",
41
- sorobanRpcUrl: "https://soroban-testnet.stellar.org",
42
- deployerAddress: "GDRHSVLY3VCEHCHCSR5MZR2ALYLCERDDFT3ULCUIELGFVYHTZFCMNU4E",
43
- ed25519VerifierAddress: "CALVIIGIOMODZMWTMKZLSD4PZFFEPWQBSYERHUFM6MH5FLWKCHW4E4G5"
165
+ if (!username) {
166
+ setResolvedAddress(null);
167
+ return;
44
168
  }
45
- },
46
- prod: {
47
- apiUrl: "https://api.accesly.xyz",
48
- walletStreamUrl: "",
49
- cognito: {
50
- region: "us-east-1",
51
- userPoolId: "TBD-prod",
52
- userPoolClientId: "TBD-prod"
53
- },
54
- stellar: {
55
- networkPassphrase: "Public Global Stellar Network ; September 2015",
56
- horizonUrl: "https://horizon.stellar.org",
57
- sorobanRpcUrl: "https://soroban-rpc.mainnet.stellar.org",
58
- deployerAddress: "TBD-prod",
59
- ed25519VerifierAddress: "TBD-prod"
169
+ let cancelled = false;
170
+ void (async () => {
171
+ try {
172
+ const stored = await walletRef.current.getStoredCredential(username);
173
+ if (cancelled) return;
174
+ setResolvedAddress(stored?.walletAddress ?? null);
175
+ } catch {
176
+ if (!cancelled) setResolvedAddress(null);
177
+ }
178
+ })();
179
+ return () => {
180
+ cancelled = true;
181
+ };
182
+ }, [walletAddress, username, walletRef]);
183
+ react.useEffect(() => {
184
+ if (!resolvedAddress) return void 0;
185
+ setOptimistic(optimisticItems.get(resolvedAddress) ?? []);
186
+ return subscribeOptimistic(resolvedAddress, setOptimistic);
187
+ }, [resolvedAddress]);
188
+ const endpointsRef = useStableRef(_internal.endpoints);
189
+ const transferScanLimit = opts.transferScanLimit ?? 50;
190
+ react.useEffect(() => {
191
+ if (!resolvedAddress) {
192
+ setIsLoading(false);
193
+ return void 0;
60
194
  }
61
- }
62
- };
63
- function AcceslyProvider(props) {
64
- const defaults = ENVIRONMENT_DEFAULTS[props.env];
65
- const apiUrl = props.apiUrl ?? defaults.apiUrl;
66
- const cognitoConfig = props.cognitoConfig ?? defaults.cognito;
67
- const telemetry = props.telemetry;
68
- const instances = react.useMemo(() => {
69
- const authClient = props.overrides?.authClient ?? new core.CognitoAuthClient(cognitoConfig);
70
- const sessionStorage = props.overrides?.sessionStorage ?? core.defaultSessionStorage();
71
- const deviceStore = props.overrides?.deviceStore ?? new core.InMemoryDeviceStore();
72
- const tokenManager = new core.TokenManager({ authClient, storage: sessionStorage });
73
- const apiClient = new core.AccesslyApiClient({
74
- baseUrl: apiUrl,
75
- getIdToken: () => tokenManager.getValidIdToken(),
76
- ...telemetry ? { telemetry } : {}
77
- });
78
- const endpoints = new core.AccesslyEndpoints(apiClient);
79
- return { authClient, sessionStorage, deviceStore, tokenManager, endpoints };
80
- }, [
81
- apiUrl,
82
- cognitoConfig.region,
83
- cognitoConfig.userPoolId,
84
- cognitoConfig.userPoolClientId,
85
- props.overrides?.authClient,
86
- props.overrides?.sessionStorage,
87
- props.overrides?.deviceStore
88
- ]);
89
- const [status, setStatus] = react.useState(() => initialStatus(instances.sessionStorage));
90
- const [username, setUsername] = react.useState(
91
- () => initialUsername(instances.sessionStorage)
92
- );
93
- const mountedRef = react.useRef(true);
94
- const refreshStatus = react.useCallback(async () => {
95
- const next = await instances.tokenManager.getStatus();
96
- const tokens = await Promise.resolve(instances.sessionStorage.load());
97
- if (mountedRef.current) {
98
- setStatus(next);
99
- setUsername(tokens?.username ?? null);
195
+ const cached = loadCache(resolvedAddress);
196
+ if (cached) {
197
+ setEvents(cached.items);
198
+ setCursors(cached.cursors);
199
+ setIsLoading(false);
100
200
  }
101
- }, [instances]);
102
- react.useEffect(() => {
103
- mountedRef.current = true;
104
- void refreshStatus();
201
+ let cancelled = false;
202
+ const channel = typeof BroadcastChannel !== "undefined" ? new BroadcastChannel(BROADCAST_CHANNEL_PREFIX + resolvedAddress) : null;
203
+ if (channel) {
204
+ channel.onmessage = (ev) => {
205
+ const data = ev.data;
206
+ if (data && !cancelled) {
207
+ setEvents(data.items);
208
+ setCursors(data.cursors);
209
+ setIsLoading(false);
210
+ }
211
+ };
212
+ }
213
+ void (async () => {
214
+ try {
215
+ const result = await endpointsRef.current.walletHistory(resolvedAddress, {
216
+ transferScanLimit
217
+ });
218
+ if (cancelled) return;
219
+ const deduped = dedupItems(result.events);
220
+ setEvents(deduped);
221
+ setCursors(result.cursors);
222
+ setIsLoading(false);
223
+ setError(null);
224
+ setHasMore(result.cursors.smartAccount !== null || result.cursors.transfers !== null);
225
+ const entry = {
226
+ items: deduped,
227
+ cursors: result.cursors,
228
+ storedAt: Date.now()
229
+ };
230
+ saveCache(resolvedAddress, entry);
231
+ channel?.postMessage(entry);
232
+ } catch (err) {
233
+ if (!cancelled) {
234
+ setError(err);
235
+ setIsLoading(false);
236
+ }
237
+ }
238
+ })();
105
239
  return () => {
106
- mountedRef.current = false;
240
+ cancelled = true;
241
+ channel?.close();
107
242
  };
108
- }, [instances]);
109
- const value = react.useMemo(
110
- () => ({
111
- appId: props.appId,
112
- env: props.env,
113
- apiUrl,
114
- cognitoConfig,
115
- authClient: instances.authClient,
116
- sessionStorage: instances.sessionStorage,
117
- tokenManager: instances.tokenManager,
118
- endpoints: instances.endpoints,
119
- deviceStore: instances.deviceStore,
120
- status,
121
- username,
122
- refreshStatus
123
- }),
124
- [props.appId, props.env, apiUrl, cognitoConfig, instances, status, username, refreshStatus]
125
- );
126
- return /* @__PURE__ */ jsxRuntime.jsx(AcceslyContext.Provider, { value, children: props.children });
127
- }
128
- function initialStatus(storage) {
129
- const tokens = storage.load();
130
- if (tokens instanceof Promise) return "bootstrapping";
131
- if (!tokens) return "anonymous";
132
- return Date.now() + 5 * 60 * 1e3 >= tokens.expiresAt ? "expired" : "authenticated";
243
+ }, [resolvedAddress, transferScanLimit, endpointsRef]);
244
+ const interval = opts.pollIntervalMs ?? POLL_INTERVAL_MS;
245
+ react.useEffect(() => {
246
+ if (!resolvedAddress || interval === 0) return void 0;
247
+ const tick = async () => {
248
+ if (typeof document !== "undefined" && document.hidden) return;
249
+ try {
250
+ const result = await endpointsRef.current.walletHistory(resolvedAddress, {
251
+ transferScanLimit
252
+ });
253
+ setEvents((prev) => mergeAndDedup(prev, result.events));
254
+ const realTxHashes = new Set(result.events.map((it) => it.txHash));
255
+ const current = optimisticItems.get(resolvedAddress) ?? [];
256
+ const remaining = current.filter((it) => !realTxHashes.has(it.txHash));
257
+ if (remaining.length !== current.length) {
258
+ optimisticItems.set(resolvedAddress, remaining);
259
+ const listeners = optimisticListeners.get(resolvedAddress);
260
+ if (listeners) for (const fn of listeners) fn(remaining);
261
+ }
262
+ } catch {
263
+ }
264
+ };
265
+ const id = setInterval(tick, interval);
266
+ return () => clearInterval(id);
267
+ }, [resolvedAddress, interval, transferScanLimit, endpointsRef]);
268
+ const loadMoreImpl = react.useCallback(async () => {
269
+ if (!resolvedAddress) return;
270
+ if (!cursors.smartAccount && !cursors.transfers) {
271
+ setHasMore(false);
272
+ return;
273
+ }
274
+ try {
275
+ const result = await endpointsRef.current.walletHistory(resolvedAddress, {
276
+ ...cursors.smartAccount ? { smartAccountCursor: cursors.smartAccount } : {},
277
+ ...cursors.transfers ? { transfersCursor: cursors.transfers } : {},
278
+ transferScanLimit
279
+ });
280
+ setEvents((prev) => mergeAndDedup(prev, result.events));
281
+ setCursors(result.cursors);
282
+ setHasMore(result.cursors.smartAccount !== null || result.cursors.transfers !== null);
283
+ } catch (err) {
284
+ setError(err);
285
+ }
286
+ }, [resolvedAddress, cursors, transferScanLimit, endpointsRef]);
287
+ const refreshImpl = react.useCallback(async () => {
288
+ if (!resolvedAddress) return;
289
+ setIsLoading(true);
290
+ try {
291
+ const result = await endpointsRef.current.walletHistory(resolvedAddress, {
292
+ transferScanLimit
293
+ });
294
+ const deduped = dedupItems(result.events);
295
+ setEvents(deduped);
296
+ setCursors(result.cursors);
297
+ setError(null);
298
+ saveCache(resolvedAddress, {
299
+ items: deduped,
300
+ cursors: result.cursors,
301
+ storedAt: Date.now()
302
+ });
303
+ } catch (err) {
304
+ setError(err);
305
+ } finally {
306
+ setIsLoading(false);
307
+ }
308
+ }, [resolvedAddress, transferScanLimit, endpointsRef]);
309
+ const combined = [...optimistic, ...events];
310
+ return {
311
+ events: combined,
312
+ isLoading,
313
+ error,
314
+ hasMore,
315
+ loadMore: loadMoreImpl,
316
+ refresh: refreshImpl
317
+ };
133
318
  }
134
- function initialUsername(storage) {
135
- const tokens = storage.load();
136
- if (tokens instanceof Promise) return null;
137
- return tokens?.username ?? null;
319
+ function dedupItems(items) {
320
+ const seen = /* @__PURE__ */ new Set();
321
+ const out = [];
322
+ for (const item of items) {
323
+ const key = `${item.type}:${item.txHash}:${item.ledger}`;
324
+ if (seen.has(key)) continue;
325
+ seen.add(key);
326
+ out.push(item);
327
+ }
328
+ out.sort((a, b) => b.ledger - a.ledger);
329
+ return out;
138
330
  }
139
- function isSorobanDeployPendingError(err) {
140
- if (!(err instanceof core.AccesslyApiError)) return false;
141
- const haystack = `${err.message ?? ""} ${err.code ?? ""}`.toLowerCase();
142
- return haystack.includes("txsorobaninvalid") || haystack.includes("soroban sendtransaction") || haystack.includes("soroban submit failed") || haystack.includes("scecexceededlimit") || haystack.includes("exceededlimit");
331
+ function mergeAndDedup(prev, fresh) {
332
+ return dedupItems([...fresh, ...prev]);
143
333
  }
144
-
145
- // src/hooks/useAccesly.ts
146
- var NotImplementedYetError = class extends Error {
147
- constructor(namespace, method) {
148
- super(
149
- `${namespace}.${method}() is not implemented yet. This namespace ships in a later release; see docs/Handoff_Fase7.md for the roadmap.`
150
- );
151
- this.name = "NotImplementedYetError";
334
+ var POLL_INTERVAL_MS, CACHE_TTL_MS, CACHE_KEY_PREFIX, BROADCAST_CHANNEL_PREFIX, optimisticItems, optimisticListeners;
335
+ var init_useWalletHistory = __esm({
336
+ "src/hooks/useWalletHistory.ts"() {
337
+ init_useAccesly();
338
+ POLL_INTERVAL_MS = 3e4;
339
+ CACHE_TTL_MS = 12 * 60 * 60 * 1e3;
340
+ CACHE_KEY_PREFIX = "accesly:history:";
341
+ BROADCAST_CHANNEL_PREFIX = "accesly:history:";
342
+ optimisticItems = /* @__PURE__ */ new Map();
343
+ optimisticListeners = /* @__PURE__ */ new Map();
152
344
  }
153
- };
345
+ });
154
346
  function useAccesly() {
155
- const ctx = react.useContext(AcceslyContext);
347
+ const ctx = react.useContext(exports.AcceslyContext);
156
348
  if (!ctx) {
157
349
  throw new Error(
158
350
  "useAccesly: missing <AcceslyProvider>. Wrap your app with <AcceslyProvider appId env>."
@@ -184,7 +376,7 @@ function useAccesly() {
184
376
  [ctx]
185
377
  );
186
378
  const { hexToBytes, hexFromBytes } = react.useMemo(() => coderHelpers(), []);
187
- const stellarConfig = ENVIRONMENT_DEFAULTS[ctx.env].stellar;
379
+ const stellarConfig = exports.ENVIRONMENT_DEFAULTS[ctx.env].stellar;
188
380
  const wallet = react.useMemo(() => {
189
381
  const c = ctx;
190
382
  const postWallet = async (params) => {
@@ -634,6 +826,24 @@ function useAccesly() {
634
826
  unsignedXdr: sim.unsignedXdr,
635
827
  signedAuthEntryXdr
636
828
  });
829
+ try {
830
+ const username = ctx.username;
831
+ if (username) {
832
+ const stored = await ctx.deviceStore.loadCredential(username);
833
+ if (stored?.walletAddress) {
834
+ const { historyOptimisticPush: historyOptimisticPush2 } = await Promise.resolve().then(() => (init_useWalletHistory(), useWalletHistory_exports));
835
+ historyOptimisticPush2(stored.walletAddress, {
836
+ type: "transfer-out",
837
+ txHash: submit.txHash,
838
+ ledger: Math.floor(Date.now() / 1e3),
839
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
840
+ to: input.destinationAddress,
841
+ amountStroops: input.amountStroops
842
+ });
843
+ }
844
+ }
845
+ } catch {
846
+ }
637
847
  return {
638
848
  txHash: submit.txHash,
639
849
  status: submit.status,
@@ -851,10 +1061,10 @@ function useAccesly() {
851
1061
  const session = react.useMemo(
852
1062
  () => ({
853
1063
  async create() {
854
- throw new NotImplementedYetError("session", "create");
1064
+ throw new exports.NotImplementedYetError("session", "create");
855
1065
  },
856
1066
  async revoke() {
857
- throw new NotImplementedYetError("session", "revoke");
1067
+ throw new exports.NotImplementedYetError("session", "revoke");
858
1068
  }
859
1069
  }),
860
1070
  []
@@ -862,16 +1072,16 @@ function useAccesly() {
862
1072
  const settings = react.useMemo(
863
1073
  () => ({
864
1074
  async addDevice() {
865
- throw new NotImplementedYetError("settings", "addDevice");
1075
+ throw new exports.NotImplementedYetError("settings", "addDevice");
866
1076
  },
867
1077
  async removeDevice() {
868
- throw new NotImplementedYetError("settings", "removeDevice");
1078
+ throw new exports.NotImplementedYetError("settings", "removeDevice");
869
1079
  },
870
1080
  async listDevices() {
871
- throw new NotImplementedYetError("settings", "listDevices");
1081
+ throw new exports.NotImplementedYetError("settings", "listDevices");
872
1082
  },
873
1083
  async updateSpendingLimit() {
874
- throw new NotImplementedYetError("settings", "updateSpendingLimit");
1084
+ throw new exports.NotImplementedYetError("settings", "updateSpendingLimit");
875
1085
  }
876
1086
  }),
877
1087
  []
@@ -879,13 +1089,13 @@ function useAccesly() {
879
1089
  const yieldOps = react.useMemo(
880
1090
  () => ({
881
1091
  async invest() {
882
- throw new NotImplementedYetError("yield", "invest");
1092
+ throw new exports.NotImplementedYetError("yield", "invest");
883
1093
  },
884
1094
  async redeem() {
885
- throw new NotImplementedYetError("yield", "redeem");
1095
+ throw new exports.NotImplementedYetError("yield", "redeem");
886
1096
  },
887
1097
  async position() {
888
- throw new NotImplementedYetError("yield", "position");
1098
+ throw new exports.NotImplementedYetError("yield", "position");
889
1099
  }
890
1100
  }),
891
1101
  []
@@ -931,6 +1141,111 @@ function base64ToBytes(s) {
931
1141
  for (let i = 0; i < bin.length; i += 1) arr[i] = bin.charCodeAt(i);
932
1142
  return arr;
933
1143
  }
1144
+ exports.NotImplementedYetError = void 0;
1145
+ var init_useAccesly = __esm({
1146
+ "src/hooks/useAccesly.ts"() {
1147
+ init_context();
1148
+ init_config();
1149
+ init_sorobanDeployStatus();
1150
+ exports.NotImplementedYetError = class extends Error {
1151
+ constructor(namespace, method) {
1152
+ super(
1153
+ `${namespace}.${method}() is not implemented yet. This namespace ships in a later release; see docs/Handoff_Fase7.md for the roadmap.`
1154
+ );
1155
+ this.name = "NotImplementedYetError";
1156
+ }
1157
+ };
1158
+ }
1159
+ });
1160
+
1161
+ // src/provider.tsx
1162
+ init_context();
1163
+ init_config();
1164
+ function AcceslyProvider(props) {
1165
+ const defaults = exports.ENVIRONMENT_DEFAULTS[props.env];
1166
+ const apiUrl = props.apiUrl ?? defaults.apiUrl;
1167
+ const cognitoConfig = props.cognitoConfig ?? defaults.cognito;
1168
+ const telemetry = props.telemetry;
1169
+ const instances = react.useMemo(() => {
1170
+ const authClient = props.overrides?.authClient ?? new core.CognitoAuthClient(cognitoConfig);
1171
+ const sessionStorage = props.overrides?.sessionStorage ?? core.defaultSessionStorage();
1172
+ const deviceStore = props.overrides?.deviceStore ?? new core.InMemoryDeviceStore();
1173
+ const tokenManager = new core.TokenManager({ authClient, storage: sessionStorage });
1174
+ const apiClient = new core.AccesslyApiClient({
1175
+ baseUrl: apiUrl,
1176
+ getIdToken: () => tokenManager.getValidIdToken(),
1177
+ ...telemetry ? { telemetry } : {}
1178
+ });
1179
+ const endpoints = new core.AccesslyEndpoints(apiClient);
1180
+ return { authClient, sessionStorage, deviceStore, tokenManager, endpoints };
1181
+ }, [
1182
+ apiUrl,
1183
+ cognitoConfig.region,
1184
+ cognitoConfig.userPoolId,
1185
+ cognitoConfig.userPoolClientId,
1186
+ props.overrides?.authClient,
1187
+ props.overrides?.sessionStorage,
1188
+ props.overrides?.deviceStore
1189
+ ]);
1190
+ const [status, setStatus] = react.useState(() => initialStatus(instances.sessionStorage));
1191
+ const [username, setUsername] = react.useState(
1192
+ () => initialUsername(instances.sessionStorage)
1193
+ );
1194
+ const mountedRef = react.useRef(true);
1195
+ const refreshStatus = react.useCallback(async () => {
1196
+ const next = await instances.tokenManager.getStatus();
1197
+ const tokens = await Promise.resolve(instances.sessionStorage.load());
1198
+ if (mountedRef.current) {
1199
+ setStatus(next);
1200
+ setUsername(tokens?.username ?? null);
1201
+ }
1202
+ }, [instances]);
1203
+ react.useEffect(() => {
1204
+ mountedRef.current = true;
1205
+ void refreshStatus();
1206
+ return () => {
1207
+ mountedRef.current = false;
1208
+ };
1209
+ }, [instances]);
1210
+ const value = react.useMemo(
1211
+ () => ({
1212
+ appId: props.appId,
1213
+ env: props.env,
1214
+ apiUrl,
1215
+ cognitoConfig,
1216
+ authClient: instances.authClient,
1217
+ sessionStorage: instances.sessionStorage,
1218
+ tokenManager: instances.tokenManager,
1219
+ endpoints: instances.endpoints,
1220
+ deviceStore: instances.deviceStore,
1221
+ status,
1222
+ username,
1223
+ refreshStatus
1224
+ }),
1225
+ [props.appId, props.env, apiUrl, cognitoConfig, instances, status, username, refreshStatus]
1226
+ );
1227
+ return /* @__PURE__ */ jsxRuntime.jsx(exports.AcceslyContext.Provider, { value, children: props.children });
1228
+ }
1229
+ function initialStatus(storage) {
1230
+ const tokens = storage.load();
1231
+ if (tokens instanceof Promise) return "bootstrapping";
1232
+ if (!tokens) return "anonymous";
1233
+ return Date.now() + 5 * 60 * 1e3 >= tokens.expiresAt ? "expired" : "authenticated";
1234
+ }
1235
+ function initialUsername(storage) {
1236
+ const tokens = storage.load();
1237
+ if (tokens instanceof Promise) return null;
1238
+ return tokens?.username ?? null;
1239
+ }
1240
+
1241
+ // src/index.ts
1242
+ init_context();
1243
+ init_config();
1244
+ init_useAccesly();
1245
+
1246
+ // src/hooks/useWalletStatus.ts
1247
+ init_useAccesly();
1248
+ init_config();
934
1249
 
935
1250
  // src/hooks/walletSubscription.ts
936
1251
  var ACTIVITY_BUFFER_MAX = 50;
@@ -1048,7 +1363,7 @@ function closeAllWalletSubscriptions() {
1048
1363
  // src/hooks/useWalletStatus.ts
1049
1364
  var POLL_BACKOFF_MS = [2e3, 5e3, 1e4, 2e4, 3e4];
1050
1365
  var STALE_THRESHOLD_MS = 6e4;
1051
- function useStableRef(value) {
1366
+ function useStableRef2(value) {
1052
1367
  const ref = react.useRef(value);
1053
1368
  ref.current = value;
1054
1369
  return ref;
@@ -1066,9 +1381,9 @@ function useWalletStatus() {
1066
1381
  const [onChain, setOnChain] = react.useState(null);
1067
1382
  const [lastSuccessAt, setLastSuccessAt] = react.useState(0);
1068
1383
  const [isStale, setIsStale] = react.useState(false);
1069
- const envDefaults = ENVIRONMENT_DEFAULTS[_internal.env];
1384
+ const envDefaults = exports.ENVIRONMENT_DEFAULTS[_internal.env];
1070
1385
  const streamUrl = envDefaults.walletStreamUrl;
1071
- const walletRef = useStableRef(wallet);
1386
+ const walletRef = useStableRef2(wallet);
1072
1387
  const doFetch = react.useCallback(async () => {
1073
1388
  if (!username) return null;
1074
1389
  try {
@@ -1092,7 +1407,7 @@ function useWalletStatus() {
1092
1407
  return null;
1093
1408
  }
1094
1409
  }, [username, walletRef]);
1095
- const doFetchRef = useStableRef(doFetch);
1410
+ const doFetchRef = useStableRef2(doFetch);
1096
1411
  react.useEffect(() => {
1097
1412
  if (!username) {
1098
1413
  setStatus("unknown");
@@ -1160,8 +1475,12 @@ function useWalletStatus() {
1160
1475
  }, [doFetchRef]);
1161
1476
  return { status, walletAddress, onChain, isStale, refresh };
1162
1477
  }
1478
+
1479
+ // src/hooks/useBalance.ts
1480
+ init_useAccesly();
1481
+ init_config();
1163
1482
  var POLL_FALLBACK_MS = 1e4;
1164
- function useStableRef2(value) {
1483
+ function useStableRef3(value) {
1165
1484
  const ref = react.useRef(value);
1166
1485
  ref.current = value;
1167
1486
  return ref;
@@ -1176,7 +1495,7 @@ function useBalance(walletAddress) {
1176
1495
  const [xlm, setXlm] = react.useState(null);
1177
1496
  const [isLoading, setIsLoading] = react.useState(true);
1178
1497
  const [error, setError] = react.useState(null);
1179
- const walletRef = useStableRef2(wallet);
1498
+ const walletRef = useStableRef3(wallet);
1180
1499
  react.useEffect(() => {
1181
1500
  if (walletAddress) {
1182
1501
  setResolvedAddress(walletAddress);
@@ -1200,9 +1519,9 @@ function useBalance(walletAddress) {
1200
1519
  cancelled = true;
1201
1520
  };
1202
1521
  }, [walletAddress, username, walletRef]);
1203
- const envDefaults = ENVIRONMENT_DEFAULTS[_internal.env];
1522
+ const envDefaults = exports.ENVIRONMENT_DEFAULTS[_internal.env];
1204
1523
  const streamUrl = envDefaults.walletStreamUrl;
1205
- const endpointsRef = useStableRef2(_internal.endpoints);
1524
+ const endpointsRef = useStableRef3(_internal.endpoints);
1206
1525
  const doFetchOnce = react.useCallback(async () => {
1207
1526
  if (!resolvedAddress) return;
1208
1527
  try {
@@ -1216,7 +1535,7 @@ function useBalance(walletAddress) {
1216
1535
  setIsLoading(false);
1217
1536
  }
1218
1537
  }, [resolvedAddress, endpointsRef]);
1219
- const doFetchRef = useStableRef2(doFetchOnce);
1538
+ const doFetchRef = useStableRef3(doFetchOnce);
1220
1539
  react.useEffect(() => {
1221
1540
  if (!resolvedAddress) {
1222
1541
  setIsLoading(false);
@@ -1261,9 +1580,13 @@ function useBalance(walletAddress) {
1261
1580
  }, [doFetchRef]);
1262
1581
  return { stroops, xlm, isLoading, error, refresh };
1263
1582
  }
1583
+
1584
+ // src/hooks/useWalletActivity.ts
1585
+ init_useAccesly();
1586
+ init_config();
1264
1587
  var POLL_FALLBACK_MS2 = 25e3;
1265
1588
  var DEFAULT_LIMIT = 20;
1266
- function useStableRef3(value) {
1589
+ function useStableRef4(value) {
1267
1590
  const ref = react.useRef(value);
1268
1591
  ref.current = value;
1269
1592
  return ref;
@@ -1278,7 +1601,7 @@ function useWalletActivity(walletAddress, opts = {}) {
1278
1601
  const [events, setEvents] = react.useState([]);
1279
1602
  const [isLoading, setIsLoading] = react.useState(true);
1280
1603
  const [error, setError] = react.useState(null);
1281
- const walletRef = useStableRef3(wallet);
1604
+ const walletRef = useStableRef4(wallet);
1282
1605
  react.useEffect(() => {
1283
1606
  if (walletAddress) {
1284
1607
  setResolvedAddress(walletAddress);
@@ -1302,9 +1625,9 @@ function useWalletActivity(walletAddress, opts = {}) {
1302
1625
  cancelled = true;
1303
1626
  };
1304
1627
  }, [walletAddress, username, walletRef]);
1305
- const envDefaults = ENVIRONMENT_DEFAULTS[_internal.env];
1628
+ const envDefaults = exports.ENVIRONMENT_DEFAULTS[_internal.env];
1306
1629
  const streamUrl = envDefaults.walletStreamUrl;
1307
- const endpointsRef = useStableRef3(_internal.endpoints);
1630
+ const endpointsRef = useStableRef4(_internal.endpoints);
1308
1631
  const doFetchOnce = react.useCallback(async () => {
1309
1632
  if (!resolvedAddress) return;
1310
1633
  try {
@@ -1322,7 +1645,7 @@ function useWalletActivity(walletAddress, opts = {}) {
1322
1645
  setIsLoading(false);
1323
1646
  }
1324
1647
  }, [resolvedAddress, limit, endpointsRef]);
1325
- const doFetchRef = useStableRef3(doFetchOnce);
1648
+ const doFetchRef = useStableRef4(doFetchOnce);
1326
1649
  react.useEffect(() => {
1327
1650
  if (!resolvedAddress) {
1328
1651
  setIsLoading(false);
@@ -1370,18 +1693,19 @@ function adaptRestEvent(ev) {
1370
1693
  }
1371
1694
 
1372
1695
  // src/index.ts
1696
+ init_useWalletHistory();
1373
1697
  var REACT_ADAPTER_VERSION = "0.0.0";
1374
1698
 
1375
- exports.AcceslyContext = AcceslyContext;
1376
1699
  exports.AcceslyProvider = AcceslyProvider;
1377
- exports.ENVIRONMENT_DEFAULTS = ENVIRONMENT_DEFAULTS;
1378
- exports.NotImplementedYetError = NotImplementedYetError;
1379
1700
  exports.REACT_ADAPTER_VERSION = REACT_ADAPTER_VERSION;
1380
1701
  exports.closeAllWalletSubscriptions = closeAllWalletSubscriptions;
1702
+ exports.historyClearOptimistic = historyClearOptimistic;
1703
+ exports.historyOptimisticPush = historyOptimisticPush;
1381
1704
  exports.subscribeToWalletEvent = subscribeToWalletEvent;
1382
1705
  exports.useAccesly = useAccesly;
1383
1706
  exports.useBalance = useBalance;
1384
1707
  exports.useWalletActivity = useWalletActivity;
1708
+ exports.useWalletHistory = useWalletHistory;
1385
1709
  exports.useWalletStatus = useWalletStatus;
1386
1710
  //# sourceMappingURL=index.cjs.map
1387
1711
  //# sourceMappingURL=index.cjs.map