@hardkas/react 0.5.0-alpha → 0.5.2-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.
package/README.md CHANGED
@@ -4,7 +4,7 @@ React hooks and provider context for integrating with the HardKAS deterministic
4
4
 
5
5
  ## ⚠️ Alpha-Only Local-Runtime Coupling Warning
6
6
 
7
- Please note that in the `v0.5.0-alpha` release, this package has direct dependencies on the **`@hardkas/bridge-local`** package to facilitate local bridge payload planning and prefix-mining simulations directly within hooks like `useBridgeLocalPlan` and `useBridgeLocalSimulation`.
7
+ Please note that in the `v0.5.2-alpha` release, this package has direct dependencies on the **`@hardkas/bridge-local`** package to facilitate local bridge payload planning and prefix-mining simulations directly within hooks like `useBridgeLocalPlan` and `useBridgeLocalSimulation`.
8
8
 
9
9
  ### 🛡️ Production & Browser Safety
10
10
 
package/dist/index.d.ts CHANGED
@@ -163,6 +163,7 @@ type MetaMaskLocalState = {
163
163
  declare function useMetaMaskLocal(): {
164
164
  state: MetaMaskLocalState;
165
165
  refresh: () => Promise<void>;
166
+ connect: () => Promise<void>;
166
167
  };
167
168
  declare function useSwitchToLocalIgra(): {
168
169
  switchChain: () => Promise<void>;
package/dist/index.js CHANGED
@@ -69,7 +69,9 @@ function HardKasProvider({ config, children, queryClient: externalQueryClient })
69
69
  "sandbox-session-created",
70
70
  "sandbox-session-paired",
71
71
  "sandbox-session-expired",
72
- "sandbox-session-disconnected"
72
+ "sandbox-session-disconnected",
73
+ "ping",
74
+ "heartbeat"
73
75
  ];
74
76
  namedEvents.forEach((type) => {
75
77
  es.addEventListener(type, (e) => {
@@ -235,7 +237,7 @@ function HardKasProvider({ config, children, queryClient: externalQueryClient })
235
237
  default: { http: [config.igraRpcUrl || "http://127.0.0.1:8545"] }
236
238
  }
237
239
  },
238
- transport: http(config.igraRpcUrl || "http://127.0.0.1:8545")
240
+ transport: http(config.igraRpcUrl || "http://127.0.0.1:8545", { retryCount: 0 })
239
241
  });
240
242
  }, [config.igraRpcUrl]);
241
243
  const value = useMemo(() => ({
@@ -372,11 +374,64 @@ function useKaspaWallet() {
372
374
  function useKaspaBalance(options = {}) {
373
375
  const { config } = useHardKas();
374
376
  const { address, name } = useKaspaWallet();
377
+ const { data: health } = useHardKasHealth();
378
+ const l1Status = health?.kaspa?.status || health?.l1?.status;
379
+ const isL1Online = l1Status === "healthy" || l1Status === "simulated-mode" || l1Status === "ok" || l1Status === "running" || l1Status === "online" || !!address && address.startsWith("kaspa:sim_");
375
380
  return useQuery3({
376
381
  queryKey: ["kaspa", "balance", address, config.kaspaRpcUrl, name],
377
382
  queryFn: async () => {
378
383
  if (!address) return 0n;
379
- const url = config.kaspaRpcUrl || "http://127.0.0.1:16110";
384
+ if (address.startsWith("kaspa:sim_") || l1Status === "simulated-mode") {
385
+ return 100000000000n;
386
+ }
387
+ let url = config.kaspaRpcUrl || "http://127.0.0.1:16110";
388
+ if (url.includes("127.0.0.1:16110") || url.includes("localhost:16110")) {
389
+ url = "ws://127.0.0.1:18210";
390
+ } else if (url.includes("127.0.0.1:18210") || url.includes("localhost:18210")) {
391
+ url = "ws://127.0.0.1:18210";
392
+ }
393
+ if (url.startsWith("ws://") || url.startsWith("wss://")) {
394
+ try {
395
+ return await new Promise((resolve, reject) => {
396
+ const ws = new WebSocket(url);
397
+ const timer = setTimeout(() => {
398
+ ws.close();
399
+ reject(new Error("WebSocket timeout"));
400
+ }, 3e3);
401
+ ws.onopen = () => {
402
+ ws.send(JSON.stringify({
403
+ id: 1,
404
+ method: "getBalanceByAddressRequest",
405
+ params: { address }
406
+ }));
407
+ };
408
+ ws.onmessage = (event) => {
409
+ clearTimeout(timer);
410
+ try {
411
+ const response = JSON.parse(event.data);
412
+ ws.close();
413
+ if (response.error) {
414
+ reject(new Error(response.error.message));
415
+ } else {
416
+ const data = response.result !== void 0 ? response.result : response.params;
417
+ resolve(BigInt(data?.balance || 0));
418
+ }
419
+ } catch (err) {
420
+ ws.close();
421
+ reject(err);
422
+ }
423
+ };
424
+ ws.onerror = (err) => {
425
+ clearTimeout(timer);
426
+ ws.close();
427
+ reject(err);
428
+ };
429
+ });
430
+ } catch (e) {
431
+ console.warn("Failed to fetch Kaspa balance via WebSocket, falling back to 0:", e);
432
+ return 0n;
433
+ }
434
+ }
380
435
  try {
381
436
  const response = await fetch(url, {
382
437
  method: "POST",
@@ -391,11 +446,10 @@ function useKaspaBalance(options = {}) {
391
446
  const json = await response.json();
392
447
  return BigInt(json.result?.balance || 0);
393
448
  } catch (e) {
394
- console.error("Failed to fetch Kaspa balance:", e);
395
449
  return 0n;
396
450
  }
397
451
  },
398
- enabled: !!address,
452
+ enabled: !!address && isL1Online,
399
453
  refetchInterval: options.refetchInterval ?? false
400
454
  });
401
455
  }
@@ -439,13 +493,23 @@ function useIgraBalance(options = {}) {
439
493
  const { address } = useIgraAccount();
440
494
  const { data: session } = useHardKasSession();
441
495
  const { config } = useHardKas();
496
+ const { data: health } = useHardKasHealth();
497
+ const l2Status = health?.igra?.status || health?.l2?.status;
498
+ const isL2Online = l2Status === "healthy" || l2Status === "ok" || l2Status === "running" || l2Status === "online" || !!address && (address.startsWith("0xsim_") || address.startsWith("kaspa:sim_") || !address.startsWith("0x"));
442
499
  return useQuery4({
443
500
  queryKey: ["igra", "balance", address, config.igraRpcUrl, session?.name],
444
501
  queryFn: async () => {
445
502
  if (!address) return 0n;
446
- return await igraClient.getBalance({ address });
503
+ if (address.startsWith("0xsim_") || !address.startsWith("0x") || l2Status === "simulated-mode") {
504
+ return 500000000000000000000n;
505
+ }
506
+ try {
507
+ return await igraClient.getBalance({ address });
508
+ } catch (e) {
509
+ return 0n;
510
+ }
447
511
  },
448
- enabled: !!address,
512
+ enabled: !!address && isL2Online,
449
513
  refetchInterval: options.refetchInterval ?? false
450
514
  });
451
515
  }
@@ -523,6 +587,15 @@ function useMetaMaskLocal() {
523
587
  setState((s) => ({ ...s, errors: [e.message] }));
524
588
  }
525
589
  }, []);
590
+ const connect = useCallback(async () => {
591
+ if (typeof window === "undefined" || !window.ethereum) return;
592
+ try {
593
+ await window.ethereum.request({ method: "eth_requestAccounts" });
594
+ await checkStatus();
595
+ } catch (e) {
596
+ setState((s) => ({ ...s, errors: [...s.errors, e.message] }));
597
+ }
598
+ }, [checkStatus]);
526
599
  useEffect3(() => {
527
600
  if (typeof window === "undefined" || !window.ethereum) return;
528
601
  const provider = window.ethereum;
@@ -539,7 +612,7 @@ function useMetaMaskLocal() {
539
612
  }
540
613
  };
541
614
  }, [checkStatus]);
542
- return { state, refresh: checkStatus };
615
+ return { state, refresh: checkStatus, connect };
543
616
  }
544
617
  function useSwitchToLocalIgra() {
545
618
  const switchChain = async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hardkas/react",
3
- "version": "0.5.0-alpha",
3
+ "version": "0.5.2-alpha",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -14,11 +14,11 @@
14
14
  "dependencies": {
15
15
  "@tanstack/react-query": "^5.61.5",
16
16
  "viem": "^2.21.51",
17
- "@hardkas/core": "0.5.0-alpha",
18
- "@hardkas/bridge-local": "0.5.0-alpha",
19
- "@hardkas/sessions": "0.5.0-alpha",
20
- "@hardkas/l2": "0.5.0-alpha",
21
- "@hardkas/kaspa-rpc": "0.5.0-alpha"
17
+ "@hardkas/core": "0.5.2-alpha",
18
+ "@hardkas/kaspa-rpc": "0.5.2-alpha",
19
+ "@hardkas/bridge-local": "0.5.2-alpha",
20
+ "@hardkas/sessions": "0.5.2-alpha",
21
+ "@hardkas/l2": "0.5.2-alpha"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@testing-library/dom": "^10.4.1",