@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/.tsbuildinfo +1 -1
- package/dist/index.cjs +488 -164
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +61 -6
- package/dist/index.d.ts +61 -6
- package/dist/index.js +473 -149
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
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
|
-
|
|
8
|
-
var
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
31
|
-
|
|
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
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
-
|
|
240
|
+
cancelled = true;
|
|
241
|
+
channel?.close();
|
|
107
242
|
};
|
|
108
|
-
}, [
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
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
|
|
140
|
-
|
|
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
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|