@hardkas/react 0.4.0-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/dist/index.js ADDED
@@ -0,0 +1,655 @@
1
+ // src/provider.tsx
2
+ import React, { createContext, useContext, useMemo } from "react";
3
+ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
4
+ import { createPublicClient, http } from "viem";
5
+ import { jsx } from "react/jsx-runtime";
6
+ var HardKasContext = createContext(void 0);
7
+ function HardKasProvider({ config, children, queryClient: externalQueryClient }) {
8
+ const queryClient = useMemo(() => externalQueryClient ?? new QueryClient(), [externalQueryClient]);
9
+ const [sseStatus, setSseStatus] = React.useState("disconnected");
10
+ const [lastEvent, setLastEvent] = React.useState(null);
11
+ const listeners = React.useRef(/* @__PURE__ */ new Set());
12
+ const eventSource = React.useRef(null);
13
+ const reconnectTimer = React.useRef(null);
14
+ const backoffMs = React.useRef(500);
15
+ const subscribe = React.useCallback((callback) => {
16
+ listeners.current.add(callback);
17
+ return () => listeners.current.delete(callback);
18
+ }, []);
19
+ const connect = React.useCallback(() => {
20
+ if (typeof window === "undefined") return;
21
+ if (!config.devServerUrl) {
22
+ setSseStatus("disconnected");
23
+ return;
24
+ }
25
+ if (typeof EventSource === "undefined") {
26
+ setSseStatus("failed");
27
+ return;
28
+ }
29
+ if (eventSource.current) {
30
+ eventSource.current.close();
31
+ }
32
+ setSseStatus("connecting");
33
+ const baseUrl = config.devServerUrl;
34
+ const url = baseUrl.endsWith("/") ? `${baseUrl}api/stream` : `${baseUrl}/api/stream`;
35
+ const es = new EventSource(url);
36
+ eventSource.current = es;
37
+ es.onopen = () => {
38
+ setSseStatus("connected");
39
+ backoffMs.current = 500;
40
+ };
41
+ es.onerror = () => {
42
+ es.close();
43
+ eventSource.current = null;
44
+ setSseStatus("reconnecting");
45
+ const nextBackoff = Math.min(backoffMs.current * 2, 1e4);
46
+ backoffMs.current = nextBackoff;
47
+ reconnectTimer.current = setTimeout(() => {
48
+ connect();
49
+ }, nextBackoff);
50
+ };
51
+ es.onmessage = (e) => {
52
+ const event = {
53
+ type: "message",
54
+ payload: e.data,
55
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
56
+ };
57
+ setLastEvent(event);
58
+ listeners.current.forEach((l) => l(event));
59
+ };
60
+ const namedEvents = [
61
+ "session-changed",
62
+ "session-created",
63
+ "session-deleted",
64
+ "health-changed",
65
+ "sandbox-session-created",
66
+ "sandbox-session-paired",
67
+ "sandbox-session-expired",
68
+ "sandbox-session-disconnected"
69
+ ];
70
+ namedEvents.forEach((type) => {
71
+ es.addEventListener(type, (e) => {
72
+ const event = {
73
+ type,
74
+ payload: e.data ? JSON.parse(e.data) : void 0,
75
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
76
+ };
77
+ setLastEvent(event);
78
+ listeners.current.forEach((l) => l(event));
79
+ });
80
+ });
81
+ }, [config.devServerUrl]);
82
+ React.useEffect(() => {
83
+ connect();
84
+ return () => {
85
+ if (eventSource.current) {
86
+ eventSource.current.close();
87
+ eventSource.current = null;
88
+ }
89
+ if (reconnectTimer.current) {
90
+ clearTimeout(reconnectTimer.current);
91
+ }
92
+ };
93
+ }, [connect]);
94
+ const igraClient = useMemo(() => {
95
+ return createPublicClient({
96
+ chain: {
97
+ id: 19416,
98
+ // Igra Local Default
99
+ name: "Igra Local",
100
+ nativeCurrency: { name: "Igra Kaspa", symbol: "iKAS", decimals: 18 },
101
+ rpcUrls: {
102
+ default: { http: [config.igraRpcUrl || "http://127.0.0.1:8545"] }
103
+ }
104
+ },
105
+ transport: http(config.igraRpcUrl || "http://127.0.0.1:8545")
106
+ });
107
+ }, [config.igraRpcUrl]);
108
+ const value = useMemo(() => ({
109
+ config: {
110
+ ...config,
111
+ localOnly: config.localOnly ?? true
112
+ },
113
+ igraClient,
114
+ queryClient,
115
+ sseStatus,
116
+ lastEvent,
117
+ subscribe
118
+ }), [config, igraClient, queryClient, sseStatus, lastEvent, subscribe]);
119
+ return /* @__PURE__ */ jsx(HardKasContext.Provider, { value, children: /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClient, children }) });
120
+ }
121
+ function useHardKas() {
122
+ const context = useContext(HardKasContext);
123
+ if (!context) {
124
+ throw new Error("useHardKas must be used within a HardKasProvider");
125
+ }
126
+ return context;
127
+ }
128
+
129
+ // src/hooks/session.ts
130
+ import { useQuery, useQueryClient } from "@tanstack/react-query";
131
+ import { useEffect } from "react";
132
+ function useHardKasSession(name) {
133
+ const { config, subscribe } = useHardKas();
134
+ const queryClient = useQueryClient();
135
+ const sessionToResolve = name || config.sessionName;
136
+ useEffect(() => {
137
+ const sync = () => queryClient.invalidateQueries({ queryKey: ["hardkas", "session"] });
138
+ return subscribe((event) => {
139
+ if (["session-changed", "session-created", "session-deleted"].includes(event.type)) {
140
+ sync();
141
+ }
142
+ });
143
+ }, [queryClient, subscribe]);
144
+ return useQuery({
145
+ queryKey: ["hardkas", "session", sessionToResolve || "active"],
146
+ queryFn: async () => {
147
+ try {
148
+ const baseUrl = config.devServerUrl || "";
149
+ const url = baseUrl ? baseUrl.endsWith("/") ? `${baseUrl}api/session` : `${baseUrl}/api/session` : "/api/session";
150
+ const response = await fetch(url);
151
+ const json = await response.json();
152
+ const active = json.active;
153
+ if (!active) return null;
154
+ return {
155
+ name: active.name,
156
+ l1: { wallet: active.l1?.wallet, address: active.l1?.address },
157
+ l2: { account: active.l2?.account, address: active.l2?.address },
158
+ bridge: { mode: active.bridge?.mode },
159
+ health: active.health || { isHealthy: true, warnings: [] },
160
+ diagnostics: json.diagnostics || []
161
+ };
162
+ } catch (e) {
163
+ console.error("Failed to fetch session from dev server:", e);
164
+ return null;
165
+ }
166
+ },
167
+ staleTime: 3e4
168
+ // Rely on SSE for updates
169
+ });
170
+ }
171
+
172
+ // src/hooks/health.ts
173
+ import { useQuery as useQuery2, useQueryClient as useQueryClient2 } from "@tanstack/react-query";
174
+ import { useEffect as useEffect2 } from "react";
175
+ function useHardKasHealth() {
176
+ const { config, subscribe } = useHardKas();
177
+ const queryClient = useQueryClient2();
178
+ useEffect2(() => {
179
+ const sync = () => queryClient.invalidateQueries({ queryKey: ["hardkas", "health"] });
180
+ return subscribe((event) => {
181
+ if (["health-changed", "session-changed"].includes(event.type)) {
182
+ sync();
183
+ }
184
+ });
185
+ }, [queryClient, subscribe]);
186
+ return useQuery2({
187
+ queryKey: ["hardkas", "health"],
188
+ queryFn: async () => {
189
+ try {
190
+ const baseUrl = config.devServerUrl || "";
191
+ const url = baseUrl ? baseUrl.endsWith("/") ? `${baseUrl}api/health` : `${baseUrl}/api/health` : "/api/health";
192
+ const res = await fetch(url);
193
+ if (!res || !res.ok) {
194
+ throw new Error("Failed to fetch health from dev server");
195
+ }
196
+ return await res.json();
197
+ } catch (e) {
198
+ console.error("Failed to fetch health from dev server:", e);
199
+ throw e;
200
+ }
201
+ },
202
+ refetchInterval: 3e4,
203
+ // Background poll as fallback
204
+ retry: 2
205
+ });
206
+ }
207
+
208
+ // src/hooks/kaspa.ts
209
+ import { useQuery as useQuery3 } from "@tanstack/react-query";
210
+ function useKaspaWallet() {
211
+ const { data: session } = useHardKasSession();
212
+ return {
213
+ name: session?.l1.wallet,
214
+ address: session?.l1.address,
215
+ isLoading: !session
216
+ };
217
+ }
218
+ function useKaspaBalance(options = {}) {
219
+ const { config } = useHardKas();
220
+ const { address, name } = useKaspaWallet();
221
+ return useQuery3({
222
+ queryKey: ["kaspa", "balance", address, config.kaspaRpcUrl, name],
223
+ queryFn: async () => {
224
+ if (!address) return 0n;
225
+ const url = config.kaspaRpcUrl || "http://127.0.0.1:16110";
226
+ try {
227
+ const response = await fetch(url, {
228
+ method: "POST",
229
+ headers: { "Content-Type": "application/json" },
230
+ body: JSON.stringify({
231
+ jsonrpc: "2.0",
232
+ id: 1,
233
+ method: "getBalanceByAddressRequest",
234
+ params: { address }
235
+ })
236
+ });
237
+ const json = await response.json();
238
+ return BigInt(json.result?.balance || 0);
239
+ } catch (e) {
240
+ console.error("Failed to fetch Kaspa balance:", e);
241
+ return 0n;
242
+ }
243
+ },
244
+ enabled: !!address,
245
+ refetchInterval: options.refetchInterval ?? false
246
+ });
247
+ }
248
+
249
+ // src/hooks/igra.ts
250
+ import { useQuery as useQuery4 } from "@tanstack/react-query";
251
+ function useIgraAccount() {
252
+ const { data: session } = useHardKasSession();
253
+ return {
254
+ name: session?.l2.account,
255
+ address: session?.l2.address,
256
+ isLoading: !session
257
+ };
258
+ }
259
+ function useIgraBalance(options = {}) {
260
+ const { igraClient } = useHardKas();
261
+ const { address } = useIgraAccount();
262
+ const { data: session } = useHardKasSession();
263
+ const { config } = useHardKas();
264
+ return useQuery4({
265
+ queryKey: ["igra", "balance", address, config.igraRpcUrl, session?.name],
266
+ queryFn: async () => {
267
+ if (!address) return 0n;
268
+ return await igraClient.getBalance({ address });
269
+ },
270
+ enabled: !!address,
271
+ refetchInterval: options.refetchInterval ?? false
272
+ });
273
+ }
274
+
275
+ // src/hooks/bridge.ts
276
+ import { useQuery as useQuery5, useMutation } from "@tanstack/react-query";
277
+ import { planBridgeEntry, simulatePrefixMining } from "@hardkas/bridge-local";
278
+ function useBridgeLocalPlan(options) {
279
+ const { data: session } = useHardKasSession();
280
+ const { config } = useHardKas();
281
+ return useQuery5({
282
+ queryKey: ["bridge", "plan", session?.name, options?.amountSompi.toString(), options?.toIgra, config.localOnly],
283
+ queryFn: async () => {
284
+ if (!session || !options) return null;
285
+ const targetAddress = options.toIgra || session.l2.address;
286
+ if (!targetAddress) throw new Error("Target Igra address is required.");
287
+ return planBridgeEntry({
288
+ fromAddress: session.l1.address,
289
+ targetEvmAddress: targetAddress,
290
+ amountSompi: options.amountSompi,
291
+ networkId: "simnet",
292
+ // Fixed for local simulation
293
+ availableUtxos: [
294
+ {
295
+ outpoint: { transactionId: "mock-utxo", index: 0 },
296
+ address: session.l1.address,
297
+ amountSompi: options.amountSompi * 2n,
298
+ scriptPublicKey: "mock-script"
299
+ }
300
+ ]
301
+ });
302
+ },
303
+ enabled: !!session && !!options
304
+ });
305
+ }
306
+ function useBridgeLocalSimulation() {
307
+ return useMutation({
308
+ mutationFn: async (params) => {
309
+ return simulatePrefixMining(params.payloadBase, params.prefix, { timeoutMs: 1e4 });
310
+ }
311
+ });
312
+ }
313
+
314
+ // src/hooks/metamask.ts
315
+ import { useState, useEffect as useEffect3, useCallback } from "react";
316
+ import { createWalletClient, custom } from "viem";
317
+ function useMetaMaskLocal() {
318
+ const [state, setState] = useState({
319
+ installed: false,
320
+ connected: false,
321
+ supported: false,
322
+ localIgraDetected: false,
323
+ errors: []
324
+ });
325
+ const checkStatus = useCallback(async () => {
326
+ if (typeof window === "undefined" || !window.ethereum) {
327
+ setState((s) => ({ ...s, installed: false }));
328
+ return;
329
+ }
330
+ try {
331
+ const provider = window.ethereum;
332
+ const chainIdHex = await provider.request({ method: "eth_chainId" });
333
+ const chainId = parseInt(chainIdHex, 16);
334
+ const accounts = await provider.request({ method: "eth_accounts" });
335
+ setState({
336
+ installed: true,
337
+ connected: accounts.length > 0,
338
+ supported: true,
339
+ account: accounts[0],
340
+ chainId,
341
+ localIgraDetected: chainId === 19416,
342
+ errors: []
343
+ });
344
+ } catch (e) {
345
+ setState((s) => ({ ...s, errors: [e.message] }));
346
+ }
347
+ }, []);
348
+ useEffect3(() => {
349
+ if (typeof window === "undefined" || !window.ethereum) return;
350
+ const provider = window.ethereum;
351
+ checkStatus();
352
+ const handleChange = () => checkStatus();
353
+ provider.on("accountsChanged", handleChange);
354
+ provider.on("chainChanged", handleChange);
355
+ provider.on("disconnect", handleChange);
356
+ return () => {
357
+ if (provider.removeListener) {
358
+ provider.removeListener("accountsChanged", handleChange);
359
+ provider.removeListener("chainChanged", handleChange);
360
+ provider.removeListener("disconnect", handleChange);
361
+ }
362
+ };
363
+ }, [checkStatus]);
364
+ return { state, refresh: checkStatus };
365
+ }
366
+ function useSwitchToLocalIgra() {
367
+ const switchChain = async () => {
368
+ if (typeof window === "undefined" || !window.ethereum) return;
369
+ try {
370
+ await window.ethereum.request({
371
+ method: "wallet_switchEthereumChain",
372
+ params: [{ chainId: "0x4bd8" }]
373
+ // 19416
374
+ });
375
+ } catch (e) {
376
+ if (e.code === 4902) {
377
+ await window.ethereum.request({
378
+ method: "wallet_addEthereumChain",
379
+ params: [{
380
+ chainId: "0x4bd8",
381
+ chainName: "HardKas Igra Local",
382
+ rpcUrls: ["http://127.0.0.1:8545"],
383
+ nativeCurrency: { name: "iKAS", symbol: "iKAS", decimals: 18 }
384
+ }]
385
+ });
386
+ }
387
+ }
388
+ };
389
+ return { switchChain };
390
+ }
391
+ function useIgraInjectedAccount(sessionL2Address) {
392
+ const { state } = useMetaMaskLocal();
393
+ const matches = !!state.account && !!sessionL2Address && state.account.toLowerCase() === sessionL2Address.toLowerCase();
394
+ return {
395
+ injectedAddress: state.account,
396
+ sessionAddress: sessionL2Address,
397
+ matches
398
+ };
399
+ }
400
+ function useLocalIgraWalletClient() {
401
+ const { state } = useMetaMaskLocal();
402
+ const getClient = useCallback(() => {
403
+ if (!state.connected || !window.ethereum) return null;
404
+ return createWalletClient({
405
+ account: state.account,
406
+ transport: custom(window.ethereum)
407
+ });
408
+ }, [state.connected, state.account]);
409
+ return { getClient };
410
+ }
411
+
412
+ // src/hooks/kasware.ts
413
+ import { useState as useState2, useEffect as useEffect4, useCallback as useCallback2 } from "react";
414
+ function useKasWareLocal() {
415
+ const [state, setState] = useState2({
416
+ installed: false,
417
+ connected: false,
418
+ supported: false,
419
+ localNetworkDetected: false,
420
+ errors: []
421
+ });
422
+ const checkStatus = useCallback2(async () => {
423
+ if (typeof window === "undefined" || !window.kasware) {
424
+ setState((s) => ({ ...s, installed: false }));
425
+ return;
426
+ }
427
+ try {
428
+ const provider = window.kasware;
429
+ const accounts = await provider.getAccounts();
430
+ const network = await provider.getNetwork();
431
+ setState({
432
+ installed: true,
433
+ connected: accounts.length > 0,
434
+ supported: true,
435
+ address: accounts[0],
436
+ network,
437
+ // Common local/dev network strings for KasWare
438
+ localNetworkDetected: ["kasparegtest", "localnet", "simnet"].includes(network),
439
+ errors: []
440
+ });
441
+ } catch (e) {
442
+ setState((s) => ({ ...s, errors: [e.message] }));
443
+ }
444
+ }, []);
445
+ useEffect4(() => {
446
+ if (typeof window === "undefined" || !window.kasware) return;
447
+ const provider = window.kasware;
448
+ checkStatus();
449
+ const handleChange = () => checkStatus();
450
+ provider.on("accountsChanged", handleChange);
451
+ provider.on("networkChanged", handleChange);
452
+ provider.on("disconnect", handleChange);
453
+ return () => {
454
+ if (provider.removeListener) {
455
+ provider.removeListener("accountsChanged", handleChange);
456
+ provider.removeListener("networkChanged", handleChange);
457
+ provider.removeListener("disconnect", handleChange);
458
+ }
459
+ };
460
+ }, [checkStatus]);
461
+ return { state, refresh: checkStatus };
462
+ }
463
+ function useConnectKasWareLocal() {
464
+ const { refresh } = useKasWareLocal();
465
+ const connect = async () => {
466
+ if (typeof window === "undefined" || !window.kasware) return null;
467
+ try {
468
+ const accounts = await window.kasware.requestAccounts();
469
+ await refresh();
470
+ return accounts[0];
471
+ } catch (e) {
472
+ console.error("KasWare connection failed:", e);
473
+ return null;
474
+ }
475
+ };
476
+ return { connect };
477
+ }
478
+ function useKasWareSessionMatch(sessionL1Address) {
479
+ const { state } = useKasWareLocal();
480
+ let matches = false;
481
+ let reason;
482
+ if (!state.installed) {
483
+ reason = "not-installed";
484
+ } else if (!state.connected) {
485
+ reason = "not-connected";
486
+ } else if (!sessionL1Address) {
487
+ reason = "no-session";
488
+ } else if (!state.localNetworkDetected) {
489
+ reason = "network-mismatch";
490
+ } else {
491
+ const normalizedWallet = state.address?.toLowerCase().trim();
492
+ const normalizedSession = sessionL1Address?.toLowerCase().trim();
493
+ matches = normalizedWallet === normalizedSession;
494
+ if (!matches) reason = "address-mismatch";
495
+ }
496
+ return {
497
+ walletAddress: state.address,
498
+ sessionAddress: sessionL1Address || void 0,
499
+ matches,
500
+ reason
501
+ };
502
+ }
503
+
504
+ // src/hooks/sandbox.ts
505
+ import { useQuery as useQuery6, useMutation as useMutation2, useQueryClient as useQueryClient3 } from "@tanstack/react-query";
506
+ import { useEffect as useEffect5 } from "react";
507
+ function useSandboxSessions() {
508
+ const { config, subscribe } = useHardKas();
509
+ const queryClient = useQueryClient3();
510
+ useEffect5(() => {
511
+ const sync = () => queryClient.invalidateQueries({ queryKey: ["sandbox", "sessions"] });
512
+ return subscribe((event) => {
513
+ if ([
514
+ "sandbox-session-created",
515
+ "sandbox-session-paired",
516
+ "sandbox-session-expired",
517
+ "sandbox-session-disconnected"
518
+ ].includes(event.type)) {
519
+ sync();
520
+ }
521
+ });
522
+ }, [queryClient, subscribe]);
523
+ return useQuery6({
524
+ queryKey: ["sandbox", "sessions"],
525
+ queryFn: async () => {
526
+ const baseUrl = config.devServerUrl || "";
527
+ const url = baseUrl ? baseUrl.endsWith("/") ? `${baseUrl}api/walletconnect/sandbox/sessions` : `${baseUrl}/api/walletconnect/sandbox/sessions` : "/api/walletconnect/sandbox/sessions";
528
+ const res = await fetch(url);
529
+ const json = await res.json();
530
+ return json.sessions;
531
+ }
532
+ });
533
+ }
534
+ function useCreateSandboxSession() {
535
+ const { config } = useHardKas();
536
+ const queryClient = useQueryClient3();
537
+ return useMutation2({
538
+ mutationFn: async () => {
539
+ const baseUrl = config.devServerUrl || "";
540
+ const url = baseUrl ? baseUrl.endsWith("/") ? `${baseUrl}api/walletconnect/sandbox/create` : `${baseUrl}/api/walletconnect/sandbox/create` : "/api/walletconnect/sandbox/create";
541
+ const res = await fetch(url, { method: "POST" });
542
+ return await res.json();
543
+ },
544
+ onSuccess: () => {
545
+ queryClient.invalidateQueries({ queryKey: ["sandbox", "sessions"] });
546
+ }
547
+ });
548
+ }
549
+ function usePairSandboxSession() {
550
+ const { config } = useHardKas();
551
+ const queryClient = useQueryClient3();
552
+ return useMutation2({
553
+ mutationFn: async (id) => {
554
+ const baseUrl = config.devServerUrl || "";
555
+ const url = baseUrl ? baseUrl.endsWith("/") ? `${baseUrl}api/walletconnect/sandbox/pair` : `${baseUrl}/api/walletconnect/sandbox/pair` : "/api/walletconnect/sandbox/pair";
556
+ const res = await fetch(url, {
557
+ method: "POST",
558
+ headers: { "Content-Type": "application/json" },
559
+ body: JSON.stringify({ id })
560
+ });
561
+ return await res.json();
562
+ },
563
+ onSuccess: () => {
564
+ queryClient.invalidateQueries({ queryKey: ["sandbox", "sessions"] });
565
+ }
566
+ });
567
+ }
568
+ function useDisconnectSandboxSession() {
569
+ const { config } = useHardKas();
570
+ const queryClient = useQueryClient3();
571
+ return useMutation2({
572
+ mutationFn: async (id) => {
573
+ const baseUrl = config.devServerUrl || "";
574
+ const url = baseUrl ? baseUrl.endsWith("/") ? `${baseUrl}api/walletconnect/sandbox/disconnect` : `${baseUrl}/api/walletconnect/sandbox/disconnect` : "/api/walletconnect/sandbox/disconnect";
575
+ const res = await fetch(url, {
576
+ method: "POST",
577
+ headers: { "Content-Type": "application/json" },
578
+ body: JSON.stringify({ id })
579
+ });
580
+ return await res.json();
581
+ },
582
+ onSuccess: () => {
583
+ queryClient.invalidateQueries({ queryKey: ["sandbox", "sessions"] });
584
+ }
585
+ });
586
+ }
587
+
588
+ // src/hooks/contracts.ts
589
+ import { useQuery as useQuery7, useMutation as useMutation3 } from "@tanstack/react-query";
590
+ function useIgraReadContract(options) {
591
+ const { igraClient, config } = useHardKas();
592
+ const { data: session } = useHardKasSession();
593
+ return useQuery7({
594
+ queryKey: ["igra", "read", options.address, options.functionName, options.args, config.igraRpcUrl, session?.name],
595
+ queryFn: async () => {
596
+ return await igraClient.readContract({
597
+ address: options.address,
598
+ abi: options.abi,
599
+ functionName: options.functionName,
600
+ args: options.args
601
+ });
602
+ },
603
+ enabled: options.enabled ?? true,
604
+ refetchInterval: options.refetchInterval ?? false
605
+ });
606
+ }
607
+ function useIgraWriteContract() {
608
+ return useMutation3({
609
+ mutationFn: async (params) => {
610
+ if (!params.walletClient) {
611
+ throw new Error("A wallet client is required to write to a contract.");
612
+ }
613
+ return await params.walletClient.writeContract({
614
+ address: params.address,
615
+ abi: params.abi,
616
+ functionName: params.functionName,
617
+ args: params.args
618
+ });
619
+ }
620
+ });
621
+ }
622
+ function useIgraWaitForReceipt() {
623
+ const { igraClient } = useHardKas();
624
+ return useMutation3({
625
+ mutationFn: async (hash) => {
626
+ return await igraClient.waitForTransactionReceipt({ hash });
627
+ }
628
+ });
629
+ }
630
+ export {
631
+ HardKasProvider,
632
+ useBridgeLocalPlan,
633
+ useBridgeLocalSimulation,
634
+ useConnectKasWareLocal,
635
+ useCreateSandboxSession,
636
+ useDisconnectSandboxSession,
637
+ useHardKas,
638
+ useHardKasHealth,
639
+ useHardKasSession,
640
+ useIgraAccount,
641
+ useIgraBalance,
642
+ useIgraInjectedAccount,
643
+ useIgraReadContract,
644
+ useIgraWaitForReceipt,
645
+ useIgraWriteContract,
646
+ useKasWareLocal,
647
+ useKasWareSessionMatch,
648
+ useKaspaBalance,
649
+ useKaspaWallet,
650
+ useLocalIgraWalletClient,
651
+ useMetaMaskLocal,
652
+ usePairSandboxSession,
653
+ useSandboxSessions,
654
+ useSwitchToLocalIgra
655
+ };
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@hardkas/react",
3
+ "version": "0.4.0-alpha",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": "./dist/index.js"
9
+ },
10
+ "peerDependencies": {
11
+ "react": ">=18",
12
+ "react-dom": ">=18"
13
+ },
14
+ "dependencies": {
15
+ "@tanstack/react-query": "^5.61.5",
16
+ "viem": "^2.21.51",
17
+ "@hardkas/bridge-local": "0.4.0-alpha",
18
+ "@hardkas/core": "0.4.0-alpha",
19
+ "@hardkas/kaspa-rpc": "0.4.0-alpha",
20
+ "@hardkas/sessions": "0.4.0-alpha",
21
+ "@hardkas/l2": "0.4.0-alpha"
22
+ },
23
+ "devDependencies": {
24
+ "@testing-library/dom": "^10.4.1",
25
+ "@testing-library/jest-dom": "^6.9.1",
26
+ "@testing-library/react": "^16.3.2",
27
+ "@types/react": "^18.3.12",
28
+ "@types/react-dom": "^18.3.1",
29
+ "@vitejs/plugin-react": "^4.7.0",
30
+ "jsdom": "^29.1.1",
31
+ "react": "^18.3.1",
32
+ "react-dom": "^18.3.1",
33
+ "tsup": "^8.3.5",
34
+ "typescript": "^5.7.2",
35
+ "vite": "^5.0.0",
36
+ "vitest": "^2.1.8"
37
+ },
38
+ "license": "MIT",
39
+ "author": "Javier Rodriguez",
40
+ "files": [
41
+ "dist",
42
+ "README.md"
43
+ ],
44
+ "scripts": {
45
+ "build": "tsup src/index.ts --format esm --dts --clean",
46
+ "test": "vitest run --passWithNoTests",
47
+ "typecheck": "tsc --noEmit"
48
+ }
49
+ }