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