@hardkas/react 0.7.3-alpha → 0.7.5-alpha

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.
Files changed (2) hide show
  1. package/dist/index.js +199 -141
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -4,8 +4,15 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
4
4
  import { createPublicClient, http } from "viem";
5
5
  import { jsx, jsxs } from "react/jsx-runtime";
6
6
  var HardKasContext = createContext(void 0);
7
- function HardKasProvider({ config, children, queryClient: externalQueryClient }) {
8
- const queryClient = useMemo(() => externalQueryClient ?? new QueryClient(), [externalQueryClient]);
7
+ function HardKasProvider({
8
+ config,
9
+ children,
10
+ queryClient: externalQueryClient
11
+ }) {
12
+ const queryClient = useMemo(
13
+ () => externalQueryClient ?? new QueryClient(),
14
+ [externalQueryClient]
15
+ );
9
16
  const [sseStatus, setSseStatus] = React.useState("disconnected");
10
17
  const [projectionStatus, setProjectionStatus] = React.useState("synced");
11
18
  const [generationId, setGenerationId] = React.useState(null);
@@ -43,34 +50,37 @@ function HardKasProvider({ config, children, queryClient: externalQueryClient })
43
50
  listeners.current.add(callback);
44
51
  return () => listeners.current.delete(callback);
45
52
  }, []);
46
- const apiFetch = React.useCallback(async (input, init) => {
47
- const headers = new Headers(init?.headers || {});
48
- if (devToken) {
49
- headers.set("Authorization", `Bearer ${devToken}`);
50
- }
51
- const method = init?.method?.toUpperCase() || "GET";
52
- if (["POST", "PUT", "PATCH", "DELETE"].includes(method)) {
53
- headers.set("X-Hardkas-Request", "true");
54
- }
55
- const mergedInit = {
56
- ...init,
57
- headers
58
- };
59
- const response = await fetch(input, mergedInit);
60
- const genHeader = response.headers?.get?.("X-Hardkas-Generation");
61
- if (genHeader) {
62
- setGenerationId((prev) => {
63
- if (prev !== genHeader) {
64
- setTimeout(() => {
65
- if (queryClient) queryClient.invalidateQueries();
66
- }, 0);
67
- return genHeader;
68
- }
69
- return prev;
70
- });
71
- }
72
- return response;
73
- }, [queryClient, devToken]);
53
+ const apiFetch = React.useCallback(
54
+ async (input, init) => {
55
+ const headers = new Headers(init?.headers || {});
56
+ if (devToken) {
57
+ headers.set("Authorization", `Bearer ${devToken}`);
58
+ }
59
+ const method = init?.method?.toUpperCase() || "GET";
60
+ if (["POST", "PUT", "PATCH", "DELETE"].includes(method)) {
61
+ headers.set("X-Hardkas-Request", "true");
62
+ }
63
+ const mergedInit = {
64
+ ...init,
65
+ headers
66
+ };
67
+ const response = await fetch(input, mergedInit);
68
+ const genHeader = response.headers?.get?.("X-Hardkas-Generation");
69
+ if (genHeader) {
70
+ setGenerationId((prev) => {
71
+ if (prev !== genHeader) {
72
+ setTimeout(() => {
73
+ if (queryClient) queryClient.invalidateQueries();
74
+ }, 0);
75
+ return genHeader;
76
+ }
77
+ return prev;
78
+ });
79
+ }
80
+ return response;
81
+ },
82
+ [queryClient, devToken]
83
+ );
74
84
  const connect = React.useCallback(() => {
75
85
  if (typeof window === "undefined") return;
76
86
  if (!config.devServerUrl) {
@@ -215,38 +225,43 @@ function HardKasProvider({ config, children, queryClient: externalQueryClient })
215
225
  window.localStorage.removeItem("hardkas:active-wallet");
216
226
  }
217
227
  }, []);
218
- const switchChain = React.useCallback(async (targetChainId) => {
219
- if (!activeProvider) {
220
- throw new Error("No active wallet connected");
221
- }
222
- const hexChainId = `0x${targetChainId.toString(16)}`;
223
- try {
224
- await activeProvider.provider.request({
225
- method: "wallet_switchEthereumChain",
226
- params: [{ chainId: hexChainId }]
227
- });
228
- setWalletChainId(targetChainId);
229
- } catch (err) {
230
- if (err.code === 4902) {
231
- if (targetChainId === 19416) {
232
- await activeProvider.provider.request({
233
- method: "wallet_addEthereumChain",
234
- params: [{
235
- chainId: hexChainId,
236
- chainName: "Igra Local",
237
- nativeCurrency: { name: "Igra Kaspa", symbol: "iKAS", decimals: 18 },
238
- rpcUrls: [config.igraRpcUrl || "http://127.0.0.1:8545"]
239
- }]
240
- });
241
- setWalletChainId(targetChainId);
228
+ const switchChain = React.useCallback(
229
+ async (targetChainId) => {
230
+ if (!activeProvider) {
231
+ throw new Error("No active wallet connected");
232
+ }
233
+ const hexChainId = `0x${targetChainId.toString(16)}`;
234
+ try {
235
+ await activeProvider.provider.request({
236
+ method: "wallet_switchEthereumChain",
237
+ params: [{ chainId: hexChainId }]
238
+ });
239
+ setWalletChainId(targetChainId);
240
+ } catch (err) {
241
+ if (err.code === 4902) {
242
+ if (targetChainId === 19416) {
243
+ await activeProvider.provider.request({
244
+ method: "wallet_addEthereumChain",
245
+ params: [
246
+ {
247
+ chainId: hexChainId,
248
+ chainName: "Igra Local",
249
+ nativeCurrency: { name: "Igra Kaspa", symbol: "iKAS", decimals: 18 },
250
+ rpcUrls: [config.igraRpcUrl || "http://127.0.0.1:8545"]
251
+ }
252
+ ]
253
+ });
254
+ setWalletChainId(targetChainId);
255
+ } else {
256
+ throw err;
257
+ }
242
258
  } else {
243
259
  throw err;
244
260
  }
245
- } else {
246
- throw err;
247
261
  }
248
- }
249
- }, [activeProvider, config.igraRpcUrl]);
262
+ },
263
+ [activeProvider, config.igraRpcUrl]
264
+ );
250
265
  React.useEffect(() => {
251
266
  if (typeof window === "undefined" || providers.length === 0 || activeProvider) return;
252
267
  const savedRdns = window.localStorage.getItem("hardkas:active-wallet");
@@ -316,70 +331,85 @@ function HardKasProvider({ config, children, queryClient: externalQueryClient })
316
331
  transport: http(config.igraRpcUrl || "http://127.0.0.1:8545", { retryCount: 0 })
317
332
  });
318
333
  }, [config.igraRpcUrl]);
319
- const value = useMemo(() => ({
320
- config: {
321
- ...config,
322
- localOnly: config.localOnly ?? true
323
- },
324
- igraClient,
325
- queryClient,
326
- sseStatus,
327
- projectionStatus,
328
- generationId,
329
- lastSyncedAt,
330
- apiFetch,
331
- lastEvent,
332
- subscribe,
333
- providers,
334
- activeProvider,
335
- walletAddress,
336
- walletChainId,
337
- connectWallet,
338
- disconnectWallet,
339
- switchChain
340
- }), [
341
- config,
342
- igraClient,
343
- queryClient,
344
- sseStatus,
345
- projectionStatus,
346
- generationId,
347
- lastSyncedAt,
348
- apiFetch,
349
- lastEvent,
350
- subscribe,
351
- providers,
352
- activeProvider,
353
- walletAddress,
354
- walletChainId,
355
- connectWallet,
356
- disconnectWallet,
357
- switchChain
358
- ]);
359
- return /* @__PURE__ */ jsx(HardKasContext.Provider, { value, children: /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClient, children: tokenMissing ? /* @__PURE__ */ jsx("div", { style: {
360
- display: "flex",
361
- flexDirection: "column",
362
- alignItems: "center",
363
- justifyContent: "center",
364
- height: "100vh",
365
- width: "100vw",
366
- backgroundColor: "#1a1a1a",
367
- color: "#f87171",
368
- fontFamily: "sans-serif",
369
- textAlign: "center",
370
- padding: "20px"
371
- }, children: /* @__PURE__ */ jsxs("div", { style: {
372
- backgroundColor: "#2d2d2d",
373
- border: "2px solid #ef4444",
374
- borderRadius: "8px",
375
- padding: "30px",
376
- maxWidth: "450px",
377
- boxShadow: "0 10px 15px -3px rgba(0, 0, 0, 0.5)"
378
- }, children: [
379
- /* @__PURE__ */ jsx("h2", { style: { color: "#ef4444", marginTop: 0 }, children: "Dashboard authentication token missing." }),
380
- /* @__PURE__ */ jsx("p", { style: { color: "#d1d5db", lineHeight: "1.5" }, children: "The dev-server is secured against local workstation CSRF and DNS rebinding attacks." }),
381
- /* @__PURE__ */ jsx("p", { style: { color: "#9ca3af", fontWeight: "bold" }, children: "Restart hardkas dashboard." })
382
- ] }) }) : children }) });
334
+ const value = useMemo(
335
+ () => ({
336
+ config: {
337
+ ...config,
338
+ localOnly: config.localOnly ?? true
339
+ },
340
+ igraClient,
341
+ queryClient,
342
+ sseStatus,
343
+ projectionStatus,
344
+ generationId,
345
+ lastSyncedAt,
346
+ apiFetch,
347
+ lastEvent,
348
+ subscribe,
349
+ providers,
350
+ activeProvider,
351
+ walletAddress,
352
+ walletChainId,
353
+ connectWallet,
354
+ disconnectWallet,
355
+ switchChain
356
+ }),
357
+ [
358
+ config,
359
+ igraClient,
360
+ queryClient,
361
+ sseStatus,
362
+ projectionStatus,
363
+ generationId,
364
+ lastSyncedAt,
365
+ apiFetch,
366
+ lastEvent,
367
+ subscribe,
368
+ providers,
369
+ activeProvider,
370
+ walletAddress,
371
+ walletChainId,
372
+ connectWallet,
373
+ disconnectWallet,
374
+ switchChain
375
+ ]
376
+ );
377
+ return /* @__PURE__ */ jsx(HardKasContext.Provider, { value, children: /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClient, children: tokenMissing ? /* @__PURE__ */ jsx(
378
+ "div",
379
+ {
380
+ style: {
381
+ display: "flex",
382
+ flexDirection: "column",
383
+ alignItems: "center",
384
+ justifyContent: "center",
385
+ height: "100vh",
386
+ width: "100vw",
387
+ backgroundColor: "#1a1a1a",
388
+ color: "#f87171",
389
+ fontFamily: "sans-serif",
390
+ textAlign: "center",
391
+ padding: "20px"
392
+ },
393
+ children: /* @__PURE__ */ jsxs(
394
+ "div",
395
+ {
396
+ style: {
397
+ backgroundColor: "#2d2d2d",
398
+ border: "2px solid #ef4444",
399
+ borderRadius: "8px",
400
+ padding: "30px",
401
+ maxWidth: "450px",
402
+ boxShadow: "0 10px 15px -3px rgba(0, 0, 0, 0.5)"
403
+ },
404
+ children: [
405
+ /* @__PURE__ */ jsx("h2", { style: { color: "#ef4444", marginTop: 0 }, children: "Dashboard authentication token missing." }),
406
+ /* @__PURE__ */ jsx("p", { style: { color: "#d1d5db", lineHeight: "1.5" }, children: "The dev-server is secured against local workstation CSRF and DNS rebinding attacks." }),
407
+ /* @__PURE__ */ jsx("p", { style: { color: "#9ca3af", fontWeight: "bold" }, children: "Restart hardkas dashboard." })
408
+ ]
409
+ }
410
+ )
411
+ }
412
+ ) : children }) });
383
413
  }
384
414
  function useHardKas() {
385
415
  const context = useContext(HardKasContext);
@@ -511,7 +541,10 @@ function useKaspaBalance(options = {}) {
511
541
  }
512
542
  }
513
543
  } catch (e) {
514
- console.warn("Failed to fetch derived simulated balance, falling back to 0:", e);
544
+ console.warn(
545
+ "Failed to fetch derived simulated balance, falling back to 0:",
546
+ e
547
+ );
515
548
  }
516
549
  return 0n;
517
550
  }
@@ -530,11 +563,13 @@ function useKaspaBalance(options = {}) {
530
563
  reject(new Error("WebSocket timeout"));
531
564
  }, 3e3);
532
565
  ws.onopen = () => {
533
- ws.send(JSON.stringify({
534
- id: 1,
535
- method: "getBalanceByAddressRequest",
536
- params: { address }
537
- }));
566
+ ws.send(
567
+ JSON.stringify({
568
+ id: 1,
569
+ method: "getBalanceByAddressRequest",
570
+ params: { address }
571
+ })
572
+ );
538
573
  };
539
574
  ws.onmessage = (event) => {
540
575
  clearTimeout(timer);
@@ -559,7 +594,10 @@ function useKaspaBalance(options = {}) {
559
594
  };
560
595
  });
561
596
  } catch (e) {
562
- console.warn("Failed to fetch Kaspa balance via WebSocket, falling back to 0:", e);
597
+ console.warn(
598
+ "Failed to fetch Kaspa balance via WebSocket, falling back to 0:",
599
+ e
600
+ );
563
601
  return 0n;
564
602
  }
565
603
  }
@@ -656,7 +694,10 @@ function useIgraBalance(options = {}) {
656
694
  }
657
695
  }
658
696
  } catch (e) {
659
- console.warn("Failed to fetch derived simulated L2 balance, falling back to 0:", e);
697
+ console.warn(
698
+ "Failed to fetch derived simulated L2 balance, falling back to 0:",
699
+ e
700
+ );
660
701
  }
661
702
  return 0n;
662
703
  }
@@ -738,7 +779,9 @@ function useMetaMaskLocal() {
738
779
  try {
739
780
  const chainIdHex = await provider.request({ method: "eth_chainId" });
740
781
  const chainId = parseInt(chainIdHex, 16);
741
- const accounts = await provider.request({ method: "eth_accounts" });
782
+ const accounts = await provider.request({
783
+ method: "eth_accounts"
784
+ });
742
785
  setState({
743
786
  installed: true,
744
787
  connected: accounts.length > 0,
@@ -794,12 +837,14 @@ function useSwitchToLocalIgra() {
794
837
  if (e.code === 4902) {
795
838
  await provider.request({
796
839
  method: "wallet_addEthereumChain",
797
- params: [{
798
- chainId: "0x4bd8",
799
- chainName: "HardKas Igra Local",
800
- rpcUrls: ["http://127.0.0.1:8545"],
801
- nativeCurrency: { name: "iKAS", symbol: "iKAS", decimals: 18 }
802
- }]
840
+ params: [
841
+ {
842
+ chainId: "0x4bd8",
843
+ chainName: "HardKas Igra Local",
844
+ rpcUrls: ["http://127.0.0.1:8545"],
845
+ nativeCurrency: { name: "iKAS", symbol: "iKAS", decimals: 18 }
846
+ }
847
+ ]
803
848
  });
804
849
  }
805
850
  }
@@ -1011,7 +1056,15 @@ function useIgraReadContract(options) {
1011
1056
  const { igraClient, config } = useHardKas();
1012
1057
  const { data: session } = useHardKasSession();
1013
1058
  return useQuery7({
1014
- queryKey: ["igra", "read", options.address, options.functionName, options.args, config.igraRpcUrl, session?.name],
1059
+ queryKey: [
1060
+ "igra",
1061
+ "read",
1062
+ options.address,
1063
+ options.functionName,
1064
+ options.args,
1065
+ config.igraRpcUrl,
1066
+ session?.name
1067
+ ],
1015
1068
  queryFn: async () => {
1016
1069
  return await igraClient.readContract({
1017
1070
  address: options.address,
@@ -1031,7 +1084,9 @@ function useIgraWriteContract() {
1031
1084
  let client = params.walletClient;
1032
1085
  if (!client) {
1033
1086
  if (!activeProvider) {
1034
- throw new Error("No active browser wallet connected and no walletClient was provided.");
1087
+ throw new Error(
1088
+ "No active browser wallet connected and no walletClient was provided."
1089
+ );
1035
1090
  }
1036
1091
  if (!walletAddress) {
1037
1092
  throw new Error("No active account address available on connected wallet.");
@@ -1195,7 +1250,9 @@ function useArtifacts(schemaFilter) {
1195
1250
  const { config, subscribe, apiFetch } = useHardKas();
1196
1251
  const queryClient = useQueryClient10();
1197
1252
  useEffect12(() => {
1198
- const sync = () => queryClient.invalidateQueries({ queryKey: ["hardkas", "artifacts", schemaFilter || "all"] });
1253
+ const sync = () => queryClient.invalidateQueries({
1254
+ queryKey: ["hardkas", "artifacts", schemaFilter || "all"]
1255
+ });
1199
1256
  return subscribe((event) => {
1200
1257
  if (["query-synced", "session-changed"].includes(event.type)) {
1201
1258
  sync();
@@ -1299,7 +1356,8 @@ function useReplayStatus() {
1299
1356
  const baseUrl = config.devServerUrl || "";
1300
1357
  const url = baseUrl ? baseUrl.endsWith("/") ? `${baseUrl}api/replay` : `${baseUrl}/api/replay` : "/api/replay";
1301
1358
  const response = await apiFetch(url);
1302
- if (!response.ok) return { replays: [], pendingReplays: [], pendingReplay: false };
1359
+ if (!response.ok)
1360
+ return { replays: [], pendingReplays: [], pendingReplay: false };
1303
1361
  const data = await response.json();
1304
1362
  const formatReplay = (r) => {
1305
1363
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hardkas/react",
3
- "version": "0.7.3-alpha",
3
+ "version": "0.7.5-alpha",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -15,10 +15,10 @@
15
15
  "dependencies": {
16
16
  "@tanstack/react-query": "^5.61.5",
17
17
  "viem": "^2.21.51",
18
- "@hardkas/core": "0.7.3-alpha",
19
- "@hardkas/kaspa-rpc": "0.7.3-alpha",
20
- "@hardkas/l2": "0.7.3-alpha",
21
- "@hardkas/sessions": "0.7.3-alpha"
18
+ "@hardkas/core": "0.7.5-alpha",
19
+ "@hardkas/sessions": "0.7.5-alpha",
20
+ "@hardkas/kaspa-rpc": "0.7.5-alpha",
21
+ "@hardkas/l2": "0.7.5-alpha"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@testing-library/dom": "^10.4.1",