@cookill/wallet-adapter 3.2.1 → 3.2.2

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/react.cjs CHANGED
@@ -1,12 +1,5 @@
1
1
  'use strict';
2
2
 
3
- var React2 = require('react');
4
- var jsxRuntime = require('react/jsx-runtime');
5
-
6
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
7
-
8
- var React2__default = /*#__PURE__*/_interopDefault(React2);
9
-
10
3
  // src/core/types.ts
11
4
  var NETWORKS = {
12
5
  mainnet: {
@@ -16,9 +9,7 @@ var NETWORKS = {
16
9
  wsUrl: "wss://mainnet.rialo.io:4102",
17
10
  explorerUrl: "https://explorer.rialo.io",
18
11
  symbol: "RLO",
19
- decimals: 9,
20
- supportsREX: true,
21
- supportsSfS: true
12
+ decimals: 9
22
13
  },
23
14
  testnet: {
24
15
  chainId: "rialo:testnet",
@@ -27,9 +18,7 @@ var NETWORKS = {
27
18
  wsUrl: "wss://testnet.rialo.io:4102",
28
19
  explorerUrl: "https://testnet.explorer.rialo.io",
29
20
  symbol: "tRLO",
30
- decimals: 9,
31
- supportsREX: true,
32
- supportsSfS: true
21
+ decimals: 9
33
22
  },
34
23
  devnet: {
35
24
  chainId: "rialo:devnet",
@@ -38,9 +27,7 @@ var NETWORKS = {
38
27
  wsUrl: "wss://devnet.rialo.io:4102",
39
28
  explorerUrl: "https://devnet.explorer.rialo.io",
40
29
  symbol: "dRLO",
41
- decimals: 9,
42
- supportsREX: true,
43
- supportsSfS: true
30
+ decimals: 9
44
31
  },
45
32
  localnet: {
46
33
  chainId: "rialo:localnet",
@@ -49,22 +36,12 @@ var NETWORKS = {
49
36
  wsUrl: "ws://localhost:4102",
50
37
  explorerUrl: "http://localhost:3000",
51
38
  symbol: "lRLO",
52
- decimals: 9,
53
- supportsREX: false,
54
- supportsSfS: false
39
+ decimals: 9
55
40
  }
56
41
  };
57
42
 
58
43
  // src/core/provider.ts
59
44
  function isInstalled() {
60
- if (typeof window === "undefined") return false;
61
- try {
62
- return !!window.rialo?.isRialo && !window.rialo?.isWebWallet;
63
- } catch {
64
- return false;
65
- }
66
- }
67
- function hasProvider() {
68
45
  if (typeof window === "undefined") return false;
69
46
  try {
70
47
  return !!window.rialo?.isRialo;
@@ -81,38 +58,6 @@ function getProvider() {
81
58
  }
82
59
  return void 0;
83
60
  }
84
- function waitForProvider(timeout = 3e3) {
85
- return new Promise((resolve) => {
86
- const existing = getProvider();
87
- if (existing) {
88
- resolve(existing);
89
- return;
90
- }
91
- let resolved = false;
92
- let checkInterval = null;
93
- let timeoutId = null;
94
- const cleanup = () => {
95
- resolved = true;
96
- if (checkInterval) clearInterval(checkInterval);
97
- if (timeoutId) clearTimeout(timeoutId);
98
- };
99
- const done = (provider) => {
100
- if (resolved) return;
101
- cleanup();
102
- resolve(provider);
103
- };
104
- checkInterval = setInterval(() => {
105
- const p = getProvider();
106
- if (p) done(p);
107
- }, 100);
108
- const onInit = () => done(getProvider());
109
- window.addEventListener("rialo#initialized", onInit, { once: true });
110
- timeoutId = setTimeout(() => {
111
- window.removeEventListener("rialo#initialized", onInit);
112
- done(void 0);
113
- }, timeout);
114
- });
115
- }
116
61
  function withTimeout(promise, ms, errorMessage = "Operation timed out") {
117
62
  let timeoutId;
118
63
  const timeout = new Promise((_, reject) => {
@@ -172,14 +117,9 @@ var SheepWallet = class {
172
117
  // =========================================================================
173
118
  // Getters (all synchronous, never block)
174
119
  // =========================================================================
175
- /** True only if the browser extension is installed (not web wallet) */
176
120
  get isInstalled() {
177
121
  return isInstalled();
178
122
  }
179
- /** True if any provider (extension or web wallet) is available */
180
- get hasProvider() {
181
- return hasProvider();
182
- }
183
123
  get connected() {
184
124
  return this._connected;
185
125
  }
@@ -204,7 +144,7 @@ var SheepWallet = class {
204
144
  async connect() {
205
145
  this._provider = getProvider();
206
146
  if (!this._provider) {
207
- throw new Error("No wallet provider found. Install Sheep Wallet extension or set up a web wallet.");
147
+ throw new Error("Sheep Wallet not installed. Get it at https://rialo.io/wallet");
208
148
  }
209
149
  try {
210
150
  const rawAccounts = await withTimeout(
@@ -311,191 +251,6 @@ var SheepWallet = class {
311
251
  );
312
252
  }
313
253
  // =========================================================================
314
- // REX — Rialo Extended Execution (Confidential Computation)
315
- // =========================================================================
316
- /**
317
- * Check if the connected wallet/network supports REX
318
- */
319
- async getREXCapabilities() {
320
- if (!this._provider?.getREXCapabilities) {
321
- return {
322
- supported: false,
323
- privacyModes: [],
324
- maxInputSize: 0,
325
- programs: []
326
- };
327
- }
328
- return withTimeout(
329
- this._provider.getREXCapabilities(),
330
- 1e4,
331
- "REX capabilities request timed out"
332
- );
333
- }
334
- /**
335
- * Submit a confidential transaction via REX
336
- * The transaction inputs are encrypted and executed in a TEE/MPC/FHE environment
337
- */
338
- async submitREXTransaction(tx) {
339
- this._ensureConnected();
340
- if (!tx.rex?.confidential) {
341
- throw new Error("Transaction must have rex.confidential = true for REX execution");
342
- }
343
- if (this._provider?.submitREXTransaction) {
344
- return withTimeout(
345
- this._provider.submitREXTransaction(tx),
346
- OPERATION_TIMEOUT,
347
- "REX transaction timed out. Please check Sheep Wallet."
348
- );
349
- }
350
- const result = await this.signAndSendTransaction(tx);
351
- return {
352
- ...result,
353
- attestation: void 0,
354
- encryptedOutput: void 0,
355
- publicOutput: void 0
356
- };
357
- }
358
- /**
359
- * Send a gasless transaction using Stake-for-Service credits
360
- * Automatically sets tx.gasless = true
361
- */
362
- async sendGaslessTransaction(tx) {
363
- this._ensureConnected();
364
- const credits = await this.getSfSCredits();
365
- if (BigInt(credits.available) <= 0n) {
366
- throw new Error("No SfS service credits available. Create a Stake-for-Service position first.");
367
- }
368
- return this.signAndSendTransaction({ ...tx, gasless: true });
369
- }
370
- // =========================================================================
371
- // SfS — Stake-for-Service (Gasless via Staking Yield)
372
- // =========================================================================
373
- /**
374
- * Get all Stake-for-Service positions for the connected account
375
- */
376
- async getSfSPositions() {
377
- this._ensureConnected();
378
- if (this._provider?.getSfSPositions) {
379
- return withTimeout(
380
- this._provider.getSfSPositions(),
381
- 1e4,
382
- "SfS positions request timed out"
383
- );
384
- }
385
- return [];
386
- }
387
- /**
388
- * Create a new Stake-for-Service position
389
- * Stakes RLO and routes a fraction of yield to service credits
390
- */
391
- async createSfSPosition(params) {
392
- this._ensureConnected();
393
- if (params.routingFraction < 0 || params.routingFraction > 1) {
394
- throw new Error("Routing fraction must be between 0.0 and 1.0");
395
- }
396
- if (!this._provider?.createSfSPosition) {
397
- throw new Error("Stake-for-Service not supported by this wallet version");
398
- }
399
- return withTimeout(
400
- this._provider.createSfSPosition(params),
401
- OPERATION_TIMEOUT,
402
- "SfS position creation timed out. Please check Sheep Wallet."
403
- );
404
- }
405
- /**
406
- * Update an existing SfS position (e.g., change routing fraction)
407
- */
408
- async updateSfSPosition(params) {
409
- this._ensureConnected();
410
- if (!this._provider?.updateSfSPosition) {
411
- throw new Error("Stake-for-Service not supported by this wallet version");
412
- }
413
- return withTimeout(
414
- this._provider.updateSfSPosition(params),
415
- OPERATION_TIMEOUT,
416
- "SfS position update timed out"
417
- );
418
- }
419
- /**
420
- * Close an SfS position and unstake
421
- */
422
- async closeSfSPosition(positionId) {
423
- this._ensureConnected();
424
- if (!this._provider?.closeSfSPosition) {
425
- throw new Error("Stake-for-Service not supported by this wallet version");
426
- }
427
- return withTimeout(
428
- this._provider.closeSfSPosition(positionId),
429
- OPERATION_TIMEOUT,
430
- "SfS position close timed out"
431
- );
432
- }
433
- /**
434
- * Get current SfS service credit balance
435
- */
436
- async getSfSCredits() {
437
- this._ensureConnected();
438
- if (this._provider?.getSfSCredits) {
439
- return withTimeout(
440
- this._provider.getSfSCredits(),
441
- 1e4,
442
- "SfS credit balance request timed out"
443
- );
444
- }
445
- return {
446
- available: "0",
447
- usedThisEpoch: "0",
448
- totalEarned: "0",
449
- estimatedPerEpoch: "0"
450
- };
451
- }
452
- // =========================================================================
453
- // Scan-to-Connect (QR-based Cross-Device Pairing)
454
- // =========================================================================
455
- /**
456
- * Generate a scan-to-connect URI from the wallet side
457
- * Returns a URI that can be displayed as QR code for dApps to scan
458
- */
459
- async createScanSession() {
460
- if (!this._provider?.createScanSession) {
461
- throw new Error("Scan-to-Connect not supported by this wallet version");
462
- }
463
- return withTimeout(
464
- this._provider.createScanSession("wallet"),
465
- 1e4,
466
- "Scan session creation timed out"
467
- );
468
- }
469
- /**
470
- * Approve a scan-to-connect session (after wallet scans dApp QR)
471
- */
472
- async approveScanSession(sessionId) {
473
- if (!this._provider?.approveScanSession) {
474
- throw new Error("Scan-to-Connect not supported by this wallet version");
475
- }
476
- const accounts = await withTimeout(
477
- this._provider.approveScanSession(sessionId),
478
- CONNECT_TIMEOUT,
479
- "Scan session approval timed out"
480
- );
481
- this._accounts = normalizeAccounts(accounts);
482
- this._connected = true;
483
- return this._accounts;
484
- }
485
- /**
486
- * Reject a scan-to-connect session
487
- */
488
- async rejectScanSession(sessionId) {
489
- if (!this._provider?.rejectScanSession) {
490
- return;
491
- }
492
- await withTimeout(
493
- this._provider.rejectScanSession(sessionId),
494
- 5e3,
495
- "Scan session rejection timed out"
496
- );
497
- }
498
- // =========================================================================
499
254
  // Balance & Network
500
255
  // =========================================================================
501
256
  async getBalance(address) {
@@ -575,1634 +330,13 @@ var SheepWallet = class {
575
330
  );
576
331
  }
577
332
  };
578
- var IconClose = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
579
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18" }),
580
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 6 12 12" })
581
- ] });
582
- var IconExtension = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
583
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16 3h5v5" }),
584
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 3H3v5" }),
585
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 22v-8.3a4 4 0 0 0-1.172-2.872L3 3" }),
586
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m15 9 6-6" })
587
- ] });
588
- var IconQR = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
589
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "3", width: "7", height: "7" }),
590
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "14", y: "3", width: "7", height: "7" }),
591
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "14", width: "7", height: "7" }),
592
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M14 14h7v7h-7z" })
593
- ] });
594
- var IconWeb = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
595
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "2", y: "3", width: "20", height: "14", rx: "2" }),
596
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M2 10h20" }),
597
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 17v4" }),
598
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 21h8" })
599
- ] });
600
- var IconCheck = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "28", height: "28", viewBox: "0 0 24 24", fill: "none", stroke: "#6EB9A8", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 6 9 17l-5-5" }) });
601
- var IconCamera = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
602
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z" }),
603
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "13", r: "3" })
604
- ] });
605
- var IconRefresh = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
606
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8" }),
607
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M21 3v5h-5" })
608
- ] });
609
- var S = {
610
- backdrop: {
611
- position: "absolute",
612
- inset: 0,
613
- backgroundColor: "rgba(0,0,0,0.6)",
614
- backdropFilter: "blur(8px)",
615
- WebkitBackdropFilter: "blur(8px)"
616
- },
617
- dialog: {
618
- pointerEvents: "auto",
619
- backgroundColor: "#011B29",
620
- borderRadius: "20px",
621
- padding: "24px",
622
- width: "100%",
623
- maxWidth: "400px",
624
- margin: "16px",
625
- boxShadow: "0 25px 60px -12px rgba(0,0,0,0.6), 0 0 0 1px rgba(255,255,255,0.05)",
626
- maxHeight: "90vh",
627
- overflow: "auto",
628
- animation: "swModalFadeIn 0.25s cubic-bezier(0.4,0,0.2,1)"
629
- },
630
- header: {
631
- display: "flex",
632
- justifyContent: "space-between",
633
- alignItems: "center",
634
- marginBottom: "20px"
635
- },
636
- title: { color: "#fff", fontSize: "18px", fontWeight: 600, margin: 0, letterSpacing: "-0.01em" },
637
- closeBtn: {
638
- background: "none",
639
- border: "none",
640
- color: "rgba(255,255,255,0.3)",
641
- cursor: "pointer",
642
- padding: "6px",
643
- borderRadius: "8px",
644
- display: "flex",
645
- alignItems: "center",
646
- justifyContent: "center",
647
- transition: "all 0.15s"
648
- },
649
- tabBar: {
650
- display: "flex",
651
- gap: "4px",
652
- padding: "4px",
653
- backgroundColor: "rgba(255,255,255,0.04)",
654
- borderRadius: "14px",
655
- marginBottom: "20px"
656
- },
657
- walletBtn: (isConnecting) => ({
658
- width: "100%",
659
- display: "flex",
660
- alignItems: "center",
661
- gap: "14px",
662
- padding: "16px",
663
- backgroundColor: "rgba(255,255,255,0.04)",
664
- border: "1px solid rgba(255,255,255,0.08)",
665
- borderRadius: "14px",
666
- cursor: isConnecting ? "wait" : "pointer",
667
- transition: "all 0.15s",
668
- color: "inherit"
669
- }),
670
- walletIcon: {
671
- width: "44px",
672
- height: "44px",
673
- borderRadius: "12px",
674
- background: "linear-gradient(135deg, #6EB9A8, #4a9a8a)",
675
- display: "flex",
676
- alignItems: "center",
677
- justifyContent: "center",
678
- color: "#fff",
679
- fontWeight: 700,
680
- fontSize: "18px",
681
- flexShrink: 0
682
- },
683
- badge: (color) => ({
684
- padding: "5px 10px",
685
- backgroundColor: `${color}10`,
686
- borderRadius: "8px",
687
- border: `1px solid ${color}18`,
688
- display: "flex",
689
- alignItems: "center",
690
- gap: "6px"
691
- }),
692
- input: {
693
- width: "100%",
694
- padding: "12px 14px",
695
- backgroundColor: "rgba(255,255,255,0.04)",
696
- border: "1px solid rgba(255,255,255,0.1)",
697
- borderRadius: "12px",
698
- color: "#fff",
699
- fontSize: "14px",
700
- marginBottom: "12px",
701
- outline: "none",
702
- boxSizing: "border-box"
703
- },
704
- primaryBtn: (loading) => ({
705
- width: "100%",
706
- padding: "12px",
707
- backgroundColor: "#6EB9A8",
708
- border: "none",
709
- borderRadius: "12px",
710
- color: "#011B29",
711
- fontSize: "14px",
712
- fontWeight: 600,
713
- cursor: loading ? "wait" : "pointer",
714
- opacity: loading ? 0.6 : 1
715
- }),
716
- error: {
717
- marginTop: "16px",
718
- padding: "12px 14px",
719
- backgroundColor: "rgba(239,68,68,0.08)",
720
- border: "1px solid rgba(239,68,68,0.15)",
721
- borderRadius: "12px",
722
- color: "#f87171",
723
- fontSize: "13px",
724
- lineHeight: 1.4
725
- }
726
- };
727
- function tabStyle(active) {
728
- return {
729
- flex: 1,
730
- padding: "10px 0",
731
- border: "none",
732
- borderRadius: "10px",
733
- fontSize: "13px",
734
- cursor: "pointer",
735
- transition: "all 0.2s",
736
- display: "flex",
737
- alignItems: "center",
738
- justifyContent: "center",
739
- gap: "6px",
740
- backgroundColor: active ? "rgba(255,255,255,0.08)" : "transparent",
741
- color: active ? "#6EB9A8" : "rgba(255,255,255,0.4)",
742
- fontWeight: active ? 600 : 400
743
- };
744
- }
745
- function ExtensionTab({ onConnect, extensionDetected, connecting, error }) {
746
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
747
- /* @__PURE__ */ jsxRuntime.jsxs(
748
- "button",
749
- {
750
- type: "button",
751
- onClick: (e) => {
752
- e.stopPropagation();
753
- if (extensionDetected) {
754
- onConnect();
755
- } else {
756
- window.open("https://rialo.io/wallet", "_blank");
757
- }
758
- },
759
- disabled: connecting,
760
- style: S.walletBtn(connecting),
761
- onMouseEnter: (e) => {
762
- e.currentTarget.style.backgroundColor = "rgba(255,255,255,0.07)";
763
- },
764
- onMouseLeave: (e) => {
765
- e.currentTarget.style.backgroundColor = "rgba(255,255,255,0.04)";
766
- },
767
- children: [
768
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: S.walletIcon, children: "S" }),
769
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1, textAlign: "left" }, children: [
770
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#fff", fontWeight: 500, fontSize: "15px", marginBottom: "2px" }, children: "Sheep Wallet" }),
771
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "12px", color: extensionDetected ? "#6EB9A8" : "rgba(255,255,255,0.4)", display: "flex", alignItems: "center", gap: "5px" }, children: connecting ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
772
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { display: "inline-block", width: "6px", height: "6px", borderRadius: "50%", backgroundColor: "#F59E0B", animation: "swModalPulse 1.2s infinite" } }),
773
- "Connecting..."
774
- ] }) : extensionDetected ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
775
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { display: "inline-block", width: "6px", height: "6px", borderRadius: "50%", backgroundColor: "#6EB9A8" } }),
776
- "Detected \u2014 Click to connect"
777
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
778
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { display: "inline-block", width: "6px", height: "6px", borderRadius: "50%", backgroundColor: "rgba(255,255,255,0.2)" } }),
779
- "Not installed"
780
- ] }) })
781
- ] }),
782
- !extensionDetected && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#6EB9A8", fontSize: "12px", fontWeight: 500, padding: "4px 10px", borderRadius: "8px", backgroundColor: "rgba(110,185,168,0.1)" }, children: "Install" })
783
- ]
784
- }
785
- ),
786
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", gap: "8px", marginTop: "16px", flexWrap: "wrap" }, children: [
787
- { label: "REX", desc: "Confidential TX", color: "#8B5CF6" },
788
- { label: "SfS", desc: "Gasless TX", color: "#F59E0B" },
789
- { label: "QR", desc: "Scan Connect", color: "#6EB9A8" }
790
- ].map((b) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: S.badge(b.color), children: [
791
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: b.color, fontSize: "11px", fontWeight: 600 }, children: b.label }),
792
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "rgba(255,255,255,0.35)", fontSize: "10px" }, children: b.desc })
793
- ] }, b.label)) }),
794
- error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: S.error, children: error.message })
795
- ] });
796
- }
797
- function ScanTab({ scanConnectRelay }) {
798
- const [scanMode, setScanMode] = React2.useState("show-qr");
799
- const [generatedURI, setGeneratedURI] = React2.useState(null);
800
- const canvasRef = React2.useRef(null);
801
- const generateSession = React2.useCallback(() => {
802
- const sessionId = crypto.randomUUID();
803
- const topic = btoa(sessionId).slice(0, 32);
804
- const uri = `rialo-wc://${sessionId}?relay=${encodeURIComponent(scanConnectRelay)}&topic=${topic}&networks=devnet`;
805
- setGeneratedURI(uri);
806
- }, [scanConnectRelay]);
807
- React2.useEffect(() => {
808
- generateSession();
809
- }, [generateSession]);
810
- React2.useEffect(() => {
811
- if (!generatedURI || !canvasRef.current) return;
812
- const canvas = canvasRef.current;
813
- const ctx = canvas.getContext("2d");
814
- if (!ctx) return;
815
- const size = 200;
816
- canvas.width = size;
817
- canvas.height = size;
818
- ctx.fillStyle = "#FFFFFF";
819
- ctx.fillRect(0, 0, size, size);
820
- ctx.fillStyle = "#011B29";
821
- const gridSize = 25;
822
- const cellSize = size / gridSize;
823
- for (let y = 0; y < gridSize; y++) {
824
- for (let x = 0; x < gridSize; x++) {
825
- const isFinderArea = x < 7 && y < 7 || x >= gridSize - 7 && y < 7 || x < 7 && y >= gridSize - 7;
826
- if (isFinderArea) {
827
- const isOuter = x === 0 || y === 0 || x === 6 || y === 6 || x === gridSize - 7 || x === gridSize - 1 || y === gridSize - 7 || y === gridSize - 1;
828
- const isInner = x >= 2 && x <= 4 && y >= 2 && y <= 4 || x >= gridSize - 5 && x <= gridSize - 3 && y >= 2 && y <= 4 || x >= 2 && x <= 4 && y >= gridSize - 5 && y <= gridSize - 3;
829
- if (isOuter || isInner) ctx.fillRect(x * cellSize, y * cellSize, cellSize, cellSize);
830
- continue;
831
- }
832
- const charIndex = (y * gridSize + x) % generatedURI.length;
833
- const charCode = generatedURI.charCodeAt(charIndex);
834
- if (charCode % 3 !== 0) ctx.fillRect(x * cellSize, y * cellSize, cellSize, cellSize);
835
- }
836
- }
837
- const logoSize = 40;
838
- const logoX = (size - logoSize) / 2;
839
- const logoY = (size - logoSize) / 2;
840
- ctx.beginPath();
841
- ctx.arc(size / 2, size / 2, logoSize / 2 + 4, 0, Math.PI * 2);
842
- ctx.fillStyle = "#FFFFFF";
843
- ctx.fill();
844
- ctx.beginPath();
845
- const r = 6;
846
- ctx.moveTo(logoX + r, logoY);
847
- ctx.lineTo(logoX + logoSize - r, logoY);
848
- ctx.quadraticCurveTo(logoX + logoSize, logoY, logoX + logoSize, logoY + r);
849
- ctx.lineTo(logoX + logoSize, logoY + logoSize - r);
850
- ctx.quadraticCurveTo(logoX + logoSize, logoY + logoSize, logoX + logoSize - r, logoY + logoSize);
851
- ctx.lineTo(logoX + r, logoY + logoSize);
852
- ctx.quadraticCurveTo(logoX, logoY + logoSize, logoX, logoY + logoSize - r);
853
- ctx.lineTo(logoX, logoY + r);
854
- ctx.quadraticCurveTo(logoX, logoY, logoX + r, logoY);
855
- ctx.fillStyle = "#6EB9A8";
856
- ctx.fill();
857
- ctx.fillStyle = "#FFFFFF";
858
- ctx.font = "bold 22px sans-serif";
859
- ctx.textAlign = "center";
860
- ctx.textBaseline = "middle";
861
- ctx.fillText("S", size / 2, size / 2 + 1);
862
- }, [generatedURI]);
863
- const stop = (e) => e.stopPropagation();
864
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
865
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", gap: "8px", marginBottom: "16px" }, children: ["show-qr", "scan-qr"].map((mode) => /* @__PURE__ */ jsxRuntime.jsx(
866
- "button",
867
- {
868
- type: "button",
869
- onClick: (e) => {
870
- stop(e);
871
- setScanMode(mode);
872
- },
873
- style: {
874
- flex: 1,
875
- padding: "8px",
876
- display: "flex",
877
- alignItems: "center",
878
- justifyContent: "center",
879
- gap: "6px",
880
- backgroundColor: scanMode === mode ? "rgba(110,185,168,0.1)" : "transparent",
881
- border: `1px solid ${scanMode === mode ? "rgba(110,185,168,0.25)" : "rgba(255,255,255,0.08)"}`,
882
- borderRadius: "10px",
883
- color: scanMode === mode ? "#6EB9A8" : "rgba(255,255,255,0.4)",
884
- fontSize: "12px",
885
- fontWeight: scanMode === mode ? 500 : 400,
886
- cursor: "pointer",
887
- transition: "all 0.15s"
888
- },
889
- children: mode === "show-qr" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
890
- /* @__PURE__ */ jsxRuntime.jsx(IconQR, {}),
891
- " Show QR"
892
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
893
- /* @__PURE__ */ jsxRuntime.jsx(IconCamera, {}),
894
- " Scan QR"
895
- ] })
896
- },
897
- mode
898
- )) }),
899
- scanMode === "show-qr" && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center" }, children: [
900
- /* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: "rgba(255,255,255,0.45)", fontSize: "13px", marginBottom: "16px", lineHeight: 1.5 }, children: "Scan this QR code with Sheep Wallet on your mobile device" }),
901
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "inline-block", padding: "16px", backgroundColor: "#FFFFFF", borderRadius: "16px", position: "relative" }, children: [
902
- [
903
- { top: -2, left: -2, borderTop: "3px solid #6EB9A8", borderLeft: "3px solid #6EB9A8", borderTopLeftRadius: "12px" },
904
- { top: -2, right: -2, borderTop: "3px solid #6EB9A8", borderRight: "3px solid #6EB9A8", borderTopRightRadius: "12px" },
905
- { bottom: -2, left: -2, borderBottom: "3px solid #6EB9A8", borderLeft: "3px solid #6EB9A8", borderBottomLeftRadius: "12px" },
906
- { bottom: -2, right: -2, borderBottom: "3px solid #6EB9A8", borderRight: "3px solid #6EB9A8", borderBottomRightRadius: "12px" }
907
- ].map((s, i) => /* @__PURE__ */ jsxRuntime.jsx("div", { style: { position: "absolute", width: "24px", height: "24px", ...s } }, i)),
908
- /* @__PURE__ */ jsxRuntime.jsx("canvas", { ref: canvasRef, style: { width: "200px", height: "200px", display: "block" } })
909
- ] }),
910
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: "16px", display: "flex", alignItems: "center", justifyContent: "center", gap: "8px" }, children: [
911
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: "7px", height: "7px", borderRadius: "50%", backgroundColor: "#6EB9A8", animation: "swModalPulse 2s infinite" } }),
912
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "rgba(255,255,255,0.4)", fontSize: "12px" }, children: "Waiting for wallet to scan..." })
913
- ] }),
914
- /* @__PURE__ */ jsxRuntime.jsxs(
915
- "button",
916
- {
917
- type: "button",
918
- onClick: (e) => {
919
- stop(e);
920
- generateSession();
921
- },
922
- style: { marginTop: "12px", padding: "8px 16px", backgroundColor: "transparent", border: "1px solid rgba(255,255,255,0.08)", borderRadius: "10px", color: "#6EB9A8", fontSize: "12px", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: "6px" },
923
- children: [
924
- /* @__PURE__ */ jsxRuntime.jsx(IconRefresh, {}),
925
- " Refresh QR"
926
- ]
927
- }
928
- )
929
- ] }),
930
- scanMode === "scan-qr" && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center" }, children: [
931
- /* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: "rgba(255,255,255,0.45)", fontSize: "13px", marginBottom: "16px", lineHeight: 1.5 }, children: "Open Sheep Wallet on another device, go to Settings \u2192 Show Connect QR, then scan it here" }),
932
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
933
- width: "100%",
934
- height: "200px",
935
- backgroundColor: "rgba(255,255,255,0.02)",
936
- borderRadius: "14px",
937
- border: "1px dashed rgba(255,255,255,0.1)",
938
- display: "flex",
939
- flexDirection: "column",
940
- alignItems: "center",
941
- justifyContent: "center",
942
- gap: "12px"
943
- }, children: [
944
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "rgba(255,255,255,0.2)" }, children: /* @__PURE__ */ jsxRuntime.jsx(IconCamera, {}) }),
945
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "rgba(255,255,255,0.3)", fontSize: "13px" }, children: "Camera access required" }),
946
- /* @__PURE__ */ jsxRuntime.jsx(
947
- "button",
948
- {
949
- type: "button",
950
- onClick: (e) => {
951
- stop(e);
952
- alert("Camera scanning requires HTTPS. This feature works in the installed extension.");
953
- },
954
- style: { padding: "8px 20px", backgroundColor: "#6EB9A8", border: "none", borderRadius: "10px", color: "#011B29", fontSize: "13px", fontWeight: 500, cursor: "pointer" },
955
- children: "Open Camera"
956
- }
957
- )
958
- ] })
959
- ] })
960
- ] });
961
- }
962
- function WebWalletTab({ onConnected }) {
963
- const { connect } = useWallet();
964
- const [mode, setMode] = React2.useState("menu");
965
- const [password, setPassword] = React2.useState("");
966
- const [mnemonic, setMnemonic] = React2.useState("");
967
- const [generatedMnemonic, setGeneratedMnemonic] = React2.useState("");
968
- const [error, setError] = React2.useState("");
969
- const [loading, setLoading] = React2.useState(false);
970
- const stop = (e) => e.stopPropagation();
971
- const webProvider = typeof window !== "undefined" ? window.rialo : null;
972
- const isWebProvider = webProvider?.isWebWallet;
973
- const hasWallet = isWebProvider && webProvider?.hasWallet?.();
974
- const isUnlocked = isWebProvider && webProvider?.isUnlocked?.();
975
- const handleAction = async (action) => {
976
- setError("");
977
- setLoading(true);
978
- try {
979
- if (!webProvider?.isWebWallet) {
980
- throw new Error("Web wallet provider not available. Make sure registerWebWallet() is called at app startup.");
981
- }
982
- if (action === "create") {
983
- if (!password || password.length < 6) throw new Error("Password must be at least 6 characters");
984
- const result = await webProvider.createWallet(password);
985
- setGeneratedMnemonic(result.mnemonic);
986
- try {
987
- await connect();
988
- onConnected();
989
- } catch {
990
- }
991
- } else if (action === "import") {
992
- if (!mnemonic.trim()) throw new Error("Please enter your recovery phrase");
993
- if (!password || password.length < 6) throw new Error("Password must be at least 6 characters");
994
- await webProvider.importWallet(mnemonic.trim(), password);
995
- try {
996
- await connect();
997
- onConnected();
998
- } catch {
999
- }
1000
- } else if (action === "unlock") {
1001
- if (!password) throw new Error("Please enter your password");
1002
- const unlocked = await webProvider.unlock(password);
1003
- if (!unlocked) throw new Error("Incorrect password");
1004
- try {
1005
- await connect();
1006
- onConnected();
1007
- } catch {
1008
- }
1009
- }
1010
- } catch (err) {
1011
- setError(err?.message || "Operation failed");
1012
- } finally {
1013
- setLoading(false);
1014
- }
1015
- };
1016
- if (generatedMnemonic) {
1017
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1018
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "14px", backgroundColor: "rgba(110,185,168,0.08)", border: "1px solid rgba(110,185,168,0.2)", borderRadius: "12px", marginBottom: "16px" }, children: [
1019
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#6EB9A8", fontSize: "12px", fontWeight: 600, marginBottom: "8px" }, children: "Wallet Created & Connected!" }),
1020
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "rgba(255,255,255,0.6)", fontSize: "11px", marginBottom: "8px" }, children: "Save your recovery phrase securely:" }),
1021
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "10px", backgroundColor: "rgba(0,0,0,0.3)", borderRadius: "8px", color: "#fff", fontSize: "12px", fontFamily: "monospace", wordBreak: "break-word", lineHeight: 1.6 }, children: generatedMnemonic })
1022
- ] }),
1023
- /* @__PURE__ */ jsxRuntime.jsx(
1024
- "button",
1025
- {
1026
- type: "button",
1027
- onClick: (e) => {
1028
- stop(e);
1029
- setGeneratedMnemonic("");
1030
- onConnected();
1031
- },
1032
- style: S.primaryBtn(false),
1033
- children: "I've Saved It \u2014 Continue"
1034
- }
1035
- )
1036
- ] });
1037
- }
1038
- if (hasWallet && !isUnlocked) {
1039
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1040
- /* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: "rgba(255,255,255,0.5)", fontSize: "13px", marginBottom: "16px" }, children: "Web wallet locked. Enter password to connect." }),
1041
- /* @__PURE__ */ jsxRuntime.jsx(
1042
- "input",
1043
- {
1044
- type: "password",
1045
- placeholder: "Password",
1046
- value: password,
1047
- onChange: (e) => setPassword(e.target.value),
1048
- onClick: stop,
1049
- onKeyDown: (e) => {
1050
- if (e.key === "Enter") handleAction("unlock");
1051
- },
1052
- style: S.input
1053
- }
1054
- ),
1055
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: (e) => {
1056
- stop(e);
1057
- handleAction("unlock");
1058
- }, disabled: loading, style: S.primaryBtn(loading), children: loading ? "Unlocking..." : "Unlock & Connect" }),
1059
- error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: S.error, children: error })
1060
- ] });
1061
- }
1062
- if (hasWallet && isUnlocked) {
1063
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1064
- /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", onClick: async (e) => {
1065
- stop(e);
1066
- setLoading(true);
1067
- try {
1068
- await connect();
1069
- onConnected();
1070
- } catch (err) {
1071
- setError(err?.message || "Failed");
1072
- } finally {
1073
- setLoading(false);
1074
- }
1075
- }, disabled: loading, style: S.walletBtn(loading), children: [
1076
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: "44px", height: "44px", borderRadius: "12px", background: "linear-gradient(135deg, #3B82F6, #6366F1)", display: "flex", alignItems: "center", justifyContent: "center", color: "#fff", flexShrink: 0 }, children: /* @__PURE__ */ jsxRuntime.jsx(IconWeb, {}) }),
1077
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1, textAlign: "left" }, children: [
1078
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#fff", fontWeight: 500, fontSize: "15px" }, children: "Web Wallet" }),
1079
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "12px", color: "#6EB9A8" }, children: loading ? "Connecting..." : "Ready \u2014 Click to connect" })
1080
- ] })
1081
- ] }),
1082
- error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: S.error, children: error })
1083
- ] });
1084
- }
1085
- if (mode === "create") {
1086
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1087
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: (e) => {
1088
- stop(e);
1089
- setMode("menu");
1090
- }, style: { background: "none", border: "none", color: "rgba(255,255,255,0.4)", cursor: "pointer", fontSize: "12px", marginBottom: "12px", padding: 0 }, children: "\u2190 Back" }),
1091
- /* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: "rgba(255,255,255,0.5)", fontSize: "13px", marginBottom: "16px" }, children: "Create a new web wallet with a generated recovery phrase." }),
1092
- /* @__PURE__ */ jsxRuntime.jsx(
1093
- "input",
1094
- {
1095
- type: "password",
1096
- placeholder: "Set password (min 6 chars)",
1097
- value: password,
1098
- onChange: (e) => setPassword(e.target.value),
1099
- onClick: stop,
1100
- style: S.input
1101
- }
1102
- ),
1103
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: (e) => {
1104
- stop(e);
1105
- handleAction("create");
1106
- }, disabled: loading, style: S.primaryBtn(loading), children: loading ? "Creating..." : "Create Wallet" }),
1107
- error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: S.error, children: error })
1108
- ] });
1109
- }
1110
- if (mode === "import") {
1111
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1112
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: (e) => {
1113
- stop(e);
1114
- setMode("menu");
1115
- }, style: { background: "none", border: "none", color: "rgba(255,255,255,0.4)", cursor: "pointer", fontSize: "12px", marginBottom: "12px", padding: 0 }, children: "\u2190 Back" }),
1116
- /* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: "rgba(255,255,255,0.5)", fontSize: "13px", marginBottom: "16px" }, children: "Import wallet from recovery phrase." }),
1117
- /* @__PURE__ */ jsxRuntime.jsx(
1118
- "textarea",
1119
- {
1120
- placeholder: "Enter 12 or 24 word recovery phrase",
1121
- value: mnemonic,
1122
- onChange: (e) => setMnemonic(e.target.value),
1123
- onClick: stop,
1124
- style: { ...S.input, minHeight: "80px", resize: "vertical", fontFamily: "monospace", fontSize: "13px" }
1125
- }
1126
- ),
1127
- /* @__PURE__ */ jsxRuntime.jsx(
1128
- "input",
1129
- {
1130
- type: "password",
1131
- placeholder: "Set password (min 6 chars)",
1132
- value: password,
1133
- onChange: (e) => setPassword(e.target.value),
1134
- onClick: stop,
1135
- style: S.input
1136
- }
1137
- ),
1138
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: (e) => {
1139
- stop(e);
1140
- handleAction("import");
1141
- }, disabled: loading, style: S.primaryBtn(loading), children: loading ? "Importing..." : "Import & Connect" }),
1142
- error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: S.error, children: error })
1143
- ] });
1144
- }
1145
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1146
- /* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: "rgba(255,255,255,0.5)", fontSize: "13px", marginBottom: "16px", lineHeight: 1.5 }, children: isWebProvider ? "Create or import a web wallet \u2014 no extension needed." : "Web wallet not available. Call registerWebWallet() at app startup." }),
1147
- isWebProvider && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "10px" }, children: [
1148
- /* @__PURE__ */ jsxRuntime.jsxs(
1149
- "button",
1150
- {
1151
- type: "button",
1152
- onClick: (e) => {
1153
- stop(e);
1154
- setMode("create");
1155
- setError("");
1156
- },
1157
- style: S.walletBtn(false),
1158
- children: [
1159
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: "40px", height: "40px", borderRadius: "10px", background: "linear-gradient(135deg, #3B82F6, #6366F1)", display: "flex", alignItems: "center", justifyContent: "center", color: "#fff", fontSize: "18px", flexShrink: 0 }, children: "+" }),
1160
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "left" }, children: [
1161
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#fff", fontWeight: 500, fontSize: "14px" }, children: "Create New Wallet" }),
1162
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "rgba(255,255,255,0.4)", fontSize: "11px" }, children: "Generate a new recovery phrase" })
1163
- ] })
1164
- ]
1165
- }
1166
- ),
1167
- /* @__PURE__ */ jsxRuntime.jsxs(
1168
- "button",
1169
- {
1170
- type: "button",
1171
- onClick: (e) => {
1172
- stop(e);
1173
- setMode("import");
1174
- setError("");
1175
- },
1176
- style: S.walletBtn(false),
1177
- children: [
1178
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: "40px", height: "40px", borderRadius: "10px", background: "linear-gradient(135deg, #F59E0B, #EF4444)", display: "flex", alignItems: "center", justifyContent: "center", color: "#fff", flexShrink: 0 }, children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
1179
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 3v12" }),
1180
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m8 11 4 4 4-4" }),
1181
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 5H4a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-4" })
1182
- ] }) }),
1183
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "left" }, children: [
1184
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#fff", fontWeight: 500, fontSize: "14px" }, children: "Import Wallet" }),
1185
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "rgba(255,255,255,0.4)", fontSize: "11px" }, children: "Use existing recovery phrase" })
1186
- ] })
1187
- ]
1188
- }
1189
- )
1190
- ] }),
1191
- error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: S.error, children: error })
1192
- ] });
1193
- }
1194
- function SuccessView({ address }) {
1195
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center", padding: "24px 0" }, children: [
1196
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
1197
- width: "56px",
1198
- height: "56px",
1199
- borderRadius: "50%",
1200
- backgroundColor: "rgba(110,185,168,0.12)",
1201
- border: "2px solid rgba(110,185,168,0.3)",
1202
- display: "flex",
1203
- alignItems: "center",
1204
- justifyContent: "center",
1205
- margin: "0 auto 16px"
1206
- }, children: /* @__PURE__ */ jsxRuntime.jsx(IconCheck, {}) }),
1207
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#fff", fontSize: "16px", fontWeight: 600, marginBottom: "6px" }, children: "Connected!" }),
1208
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "rgba(255,255,255,0.4)", fontSize: "13px", fontFamily: "monospace" }, children: formatAddress(address) })
1209
- ] });
1210
- }
1211
- function WalletModal({ scanConnectRelay }) {
1212
- const { state, connect, closeModal } = useWallet();
1213
- const [activeTab, setActiveTab] = React2.useState("extension");
1214
- const [isMobile, setIsMobile] = React2.useState(false);
1215
- const [showSuccess, setShowSuccess] = React2.useState(false);
1216
- const statusOnOpenRef = React2.useRef(null);
1217
- const successTimerRef = React2.useRef(null);
1218
- const [dragY, setDragY] = React2.useState(0);
1219
- const [isDragging, setIsDragging] = React2.useState(false);
1220
- const dragStartRef = React2.useRef(0);
1221
- const extensionDetected = isInstalled();
1222
- React2.useEffect(() => {
1223
- const check = () => setIsMobile(window.innerWidth < 640);
1224
- check();
1225
- window.addEventListener("resize", check);
1226
- return () => window.removeEventListener("resize", check);
1227
- }, []);
1228
- React2.useEffect(() => {
1229
- if (state.isModalOpen) {
1230
- statusOnOpenRef.current = state.status;
1231
- setActiveTab("extension");
1232
- setShowSuccess(false);
1233
- } else {
1234
- statusOnOpenRef.current = null;
1235
- }
1236
- }, [state.isModalOpen]);
1237
- React2.useEffect(() => {
1238
- if (state.isModalOpen && state.status === "connected" && state.accounts.length > 0 && !showSuccess && statusOnOpenRef.current !== "connected") {
1239
- setShowSuccess(true);
1240
- successTimerRef.current = setTimeout(() => {
1241
- closeModal();
1242
- setShowSuccess(false);
1243
- }, 1500);
1244
- }
1245
- return () => {
1246
- if (successTimerRef.current) clearTimeout(successTimerRef.current);
1247
- };
1248
- }, [state.isModalOpen, state.status, state.accounts.length, showSuccess, closeModal]);
1249
- React2.useEffect(() => {
1250
- if (!state.isModalOpen) {
1251
- setShowSuccess(false);
1252
- setDragY(0);
1253
- setIsDragging(false);
1254
- }
1255
- }, [state.isModalOpen]);
1256
- const handleExtensionConnect = React2.useCallback(async () => {
1257
- try {
1258
- await connect();
1259
- } catch {
1260
- }
1261
- }, [connect]);
1262
- const handleTouchStart = (e) => {
1263
- if (!isMobile) return;
1264
- dragStartRef.current = e.touches[0].clientY;
1265
- setIsDragging(true);
1266
- };
1267
- const handleTouchMove = (e) => {
1268
- if (!isDragging || !isMobile) return;
1269
- const delta = e.touches[0].clientY - dragStartRef.current;
1270
- if (delta > 0) setDragY(delta);
1271
- };
1272
- const handleTouchEnd = () => {
1273
- if (!isMobile) return;
1274
- setIsDragging(false);
1275
- if (dragY > 120) closeModal();
1276
- setDragY(0);
1277
- };
1278
- if (!state.isModalOpen) return null;
1279
- const stop = (e) => e.stopPropagation();
1280
- const content = /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: showSuccess && state.status === "connected" && state.accounts.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(SuccessView, { address: state.accounts[0]?.address || "" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1281
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: S.tabBar, children: [
1282
- /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", onClick: (e) => {
1283
- stop(e);
1284
- setActiveTab("extension");
1285
- }, style: tabStyle(activeTab === "extension"), children: [
1286
- /* @__PURE__ */ jsxRuntime.jsx(IconExtension, {}),
1287
- " Extension"
1288
- ] }),
1289
- /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", onClick: (e) => {
1290
- stop(e);
1291
- setActiveTab("scan");
1292
- }, style: tabStyle(activeTab === "scan"), children: [
1293
- /* @__PURE__ */ jsxRuntime.jsx(IconQR, {}),
1294
- " Scan"
1295
- ] }),
1296
- /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", onClick: (e) => {
1297
- stop(e);
1298
- setActiveTab("webwallet");
1299
- }, style: tabStyle(activeTab === "webwallet"), children: [
1300
- /* @__PURE__ */ jsxRuntime.jsx(IconWeb, {}),
1301
- " Web Wallet"
1302
- ] })
1303
- ] }),
1304
- activeTab === "extension" && /* @__PURE__ */ jsxRuntime.jsx(
1305
- ExtensionTab,
1306
- {
1307
- onConnect: handleExtensionConnect,
1308
- extensionDetected,
1309
- connecting: state.status === "connecting",
1310
- error: state.error
1311
- }
1312
- ),
1313
- activeTab === "scan" && /* @__PURE__ */ jsxRuntime.jsx(ScanTab, { scanConnectRelay }),
1314
- activeTab === "webwallet" && /* @__PURE__ */ jsxRuntime.jsx(WebWalletTab, { onConnected: () => {
1315
- } }),
1316
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
1317
- marginTop: "24px",
1318
- textAlign: "center",
1319
- color: "rgba(255,255,255,0.2)",
1320
- fontSize: "11px",
1321
- paddingTop: "16px",
1322
- borderTop: "1px solid rgba(255,255,255,0.04)"
1323
- }, children: "Powered by Rialo Network" })
1324
- ] }) });
1325
- const keyframes = `
1326
- @keyframes swModalFadeIn {
1327
- from { opacity: 0; transform: scale(0.97) translateY(8px); }
1328
- to { opacity: 1; transform: scale(1) translateY(0); }
1329
- }
1330
- @keyframes swModalSlideUp {
1331
- from { transform: translateY(100%); }
1332
- to { transform: translateY(0); }
1333
- }
1334
- @keyframes swModalPulse {
1335
- 0%, 100% { opacity: 1; }
1336
- 50% { opacity: 0.3; }
1337
- }
1338
- `;
1339
- if (isMobile) {
1340
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "fixed", inset: 0, zIndex: 9999 }, children: [
1341
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: S.backdrop, onClick: closeModal }),
1342
- /* @__PURE__ */ jsxRuntime.jsxs(
1343
- "div",
1344
- {
1345
- onTouchStart: handleTouchStart,
1346
- onTouchMove: handleTouchMove,
1347
- onTouchEnd: handleTouchEnd,
1348
- style: {
1349
- position: "fixed",
1350
- bottom: 0,
1351
- left: 0,
1352
- right: 0,
1353
- backgroundColor: "#011B29",
1354
- borderTopLeftRadius: "24px",
1355
- borderTopRightRadius: "24px",
1356
- padding: "0 20px 28px",
1357
- maxHeight: "85vh",
1358
- overflow: "auto",
1359
- boxShadow: "0 -8px 40px rgba(0,0,0,0.5)",
1360
- transform: `translateY(${dragY}px)`,
1361
- transition: isDragging ? "none" : "transform 0.3s cubic-bezier(0.4,0,0.2,1)",
1362
- animation: isDragging ? "none" : "swModalSlideUp 0.35s cubic-bezier(0.4,0,0.2,1)"
1363
- },
1364
- children: [
1365
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", justifyContent: "center", padding: "12px 0 16px", cursor: "grab", touchAction: "none" }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: "36px", height: "4px", borderRadius: "2px", backgroundColor: "rgba(255,255,255,0.12)" } }) }),
1366
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: S.header, children: [
1367
- /* @__PURE__ */ jsxRuntime.jsx("h2", { style: S.title, children: "Connect Wallet" }),
1368
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: closeModal, style: S.closeBtn, children: /* @__PURE__ */ jsxRuntime.jsx(IconClose, {}) })
1369
- ] }),
1370
- content
1371
- ]
1372
- }
1373
- ),
1374
- /* @__PURE__ */ jsxRuntime.jsx("style", { children: keyframes })
1375
- ] });
1376
- }
1377
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "fixed", inset: 0, zIndex: 9999 }, children: [
1378
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: S.backdrop, onClick: closeModal }),
1379
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { position: "fixed", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", pointerEvents: "none" }, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: S.dialog, children: [
1380
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: S.header, children: [
1381
- /* @__PURE__ */ jsxRuntime.jsx("h2", { style: S.title, children: "Connect Wallet" }),
1382
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: closeModal, style: S.closeBtn, children: /* @__PURE__ */ jsxRuntime.jsx(IconClose, {}) })
1383
- ] }),
1384
- content
1385
- ] }) }),
1386
- /* @__PURE__ */ jsxRuntime.jsx("style", { children: keyframes })
1387
- ] });
1388
- }
1389
- var initialState = {
1390
- status: "disconnected",
1391
- accounts: [],
1392
- network: "devnet",
1393
- balance: null,
1394
- error: null,
1395
- isModalOpen: false,
1396
- scanConnectStatus: "idle"
1397
- };
1398
- function walletReducer(state, action) {
1399
- switch (action.type) {
1400
- case "CONNECTING":
1401
- return { ...state, status: "connecting", error: null };
1402
- case "CONNECTED":
1403
- return {
1404
- ...state,
1405
- status: "connected",
1406
- accounts: action.accounts,
1407
- network: action.network,
1408
- error: null
1409
- // Do NOT close modal here — let the modal show success state first
1410
- };
1411
- case "DISCONNECTED":
1412
- return { ...state, status: "disconnected", accounts: [], balance: null, error: null };
1413
- case "ERROR":
1414
- return { ...state, status: "error", error: action.error };
1415
- case "SET_BALANCE":
1416
- return { ...state, balance: action.balance };
1417
- case "SET_NETWORK":
1418
- return { ...state, network: action.network };
1419
- case "SET_ACCOUNTS":
1420
- return { ...state, accounts: action.accounts };
1421
- case "OPEN_MODAL":
1422
- return { ...state, isModalOpen: true };
1423
- case "CLOSE_MODAL":
1424
- return { ...state, isModalOpen: false, scanConnectStatus: "idle" };
1425
- case "RESET_ERROR":
1426
- return { ...state, error: null, status: state.accounts.length > 0 ? "connected" : "disconnected" };
1427
- case "SET_SCAN_STATUS":
1428
- return { ...state, scanConnectStatus: action.status };
1429
- default:
1430
- return state;
1431
- }
1432
- }
1433
- var WalletContext = React2.createContext(null);
1434
- var DEFAULT_WALLETS = [
1435
- {
1436
- id: "sheep-wallet",
1437
- name: "Sheep Wallet",
1438
- icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHJ4PSI4IiBmaWxsPSIjMDExQjI5Ii8+PHRleHQgeD0iNTAlIiB5PSI1NSUiIGRvbWluYW50LWJhc2VsaW5lPSJtaWRkbGUiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXdlaWdodD0iYm9sZCIgZm9udC1zaXplPSIxNiIgZmlsbD0iIzZFQjlBOCI+Uzwvc2VsZj48L3N2Zz4=",
1439
- downloadUrl: "https://rialo.io/wallet",
1440
- supportsREX: true,
1441
- supportsSfS: true,
1442
- supportsScanConnect: true
1443
- }
1444
- ];
1445
- function WalletProvider({
1446
- children,
1447
- network: initialNetwork = "devnet",
1448
- autoConnect = true,
1449
- wallets: customWallets = [],
1450
- scanConnectRelay = "wss://relay.rialo.io",
1451
- onConnect,
1452
- onDisconnect,
1453
- onError,
1454
- onNetworkChange
1455
- }) {
1456
- const [state, dispatch] = React2.useReducer(walletReducer, {
1457
- ...initialState,
1458
- network: initialNetwork
1459
- });
1460
- const walletRef = React2.useRef(null);
1461
- const providerRef = React2.useRef(void 0);
1462
- const connectingRef = React2.useRef(false);
1463
- const mountedRef = React2.useRef(true);
1464
- React2.useEffect(() => {
1465
- mountedRef.current = true;
1466
- walletRef.current = new SheepWallet();
1467
- waitForProvider(3e3).then((provider) => {
1468
- if (mountedRef.current) {
1469
- providerRef.current = provider;
1470
- }
1471
- });
1472
- return () => {
1473
- mountedRef.current = false;
1474
- walletRef.current?.destroy();
1475
- };
1476
- }, []);
1477
- React2.useEffect(() => {
1478
- const setupEvents = async () => {
1479
- const provider = await waitForProvider(3e3);
1480
- if (!provider || !mountedRef.current) return;
1481
- providerRef.current = provider;
1482
- const cleanups = [];
1483
- cleanups.push(
1484
- provider.on("disconnect", () => {
1485
- if (!mountedRef.current) return;
1486
- dispatch({ type: "DISCONNECTED" });
1487
- onDisconnect?.();
1488
- })
1489
- );
1490
- cleanups.push(
1491
- provider.on("accountsChanged", (data) => {
1492
- if (!mountedRef.current) return;
1493
- const accounts = normalizeAccounts(data);
1494
- dispatch({ type: "SET_ACCOUNTS", accounts });
1495
- })
1496
- );
1497
- cleanups.push(
1498
- provider.on("networkChanged", (data) => {
1499
- if (!mountedRef.current) return;
1500
- const { network } = data;
1501
- if (network) {
1502
- dispatch({ type: "SET_NETWORK", network });
1503
- onNetworkChange?.(network);
1504
- }
1505
- })
1506
- );
1507
- return () => {
1508
- cleanups.forEach((fn) => {
1509
- try {
1510
- fn();
1511
- } catch {
1512
- }
1513
- });
1514
- };
1515
- };
1516
- const cleanup = setupEvents();
1517
- return () => {
1518
- cleanup.then((fn) => fn?.());
1519
- };
1520
- }, [onDisconnect, onNetworkChange]);
1521
- React2.useEffect(() => {
1522
- if (!autoConnect) return;
1523
- if (state.status === "connected" || state.status === "connecting") return;
1524
- const tryAutoConnect = async () => {
1525
- const wallet = walletRef.current;
1526
- if (!wallet || !hasProvider()) return;
1527
- try {
1528
- const accounts = await wallet.checkSession();
1529
- if (accounts && accounts.length > 0 && mountedRef.current) {
1530
- dispatch({ type: "CONNECTED", accounts, network: wallet.network });
1531
- onConnect?.(accounts);
1532
- }
1533
- } catch {
1534
- }
1535
- };
1536
- const timer = setTimeout(tryAutoConnect, 500);
1537
- return () => clearTimeout(timer);
1538
- }, [autoConnect, onConnect]);
1539
- React2.useEffect(() => {
1540
- if (state.status !== "connected" || state.accounts.length === 0) return;
1541
- const refresh = async () => {
1542
- const wallet = walletRef.current;
1543
- if (!wallet || !mountedRef.current) return;
1544
- try {
1545
- const balance = await wallet.getBalance();
1546
- if (mountedRef.current) {
1547
- dispatch({ type: "SET_BALANCE", balance });
1548
- }
1549
- } catch {
1550
- }
1551
- };
1552
- refresh();
1553
- const interval = setInterval(refresh, 3e4);
1554
- return () => clearInterval(interval);
1555
- }, [state.status, state.accounts]);
1556
- const connect = React2.useCallback(async () => {
1557
- if (connectingRef.current) {
1558
- throw new Error("Connection already in progress");
1559
- }
1560
- const wallet = walletRef.current;
1561
- if (!wallet) {
1562
- const err = new Error("Wallet not initialized");
1563
- dispatch({ type: "ERROR", error: err });
1564
- throw err;
1565
- }
1566
- if (!hasProvider()) {
1567
- dispatch({ type: "OPEN_MODAL" });
1568
- return [];
1569
- }
1570
- connectingRef.current = true;
1571
- dispatch({ type: "CONNECTING" });
1572
- try {
1573
- const accounts = await wallet.connect();
1574
- if (mountedRef.current) {
1575
- dispatch({ type: "CONNECTED", accounts, network: wallet.network });
1576
- onConnect?.(accounts);
1577
- }
1578
- return accounts;
1579
- } catch (error) {
1580
- const err = error instanceof Error ? error : new Error(String(error));
1581
- if (mountedRef.current) {
1582
- dispatch({ type: "ERROR", error: err });
1583
- onError?.(err);
1584
- }
1585
- throw err;
1586
- } finally {
1587
- connectingRef.current = false;
1588
- }
1589
- }, [onConnect, onError]);
1590
- const disconnect = React2.useCallback(async () => {
1591
- const wallet = walletRef.current;
1592
- if (!wallet) return;
1593
- try {
1594
- await wallet.disconnect();
1595
- } catch {
1596
- }
1597
- if (mountedRef.current) {
1598
- dispatch({ type: "DISCONNECTED" });
1599
- onDisconnect?.();
1600
- }
1601
- }, [onDisconnect]);
1602
- const refreshBalance = React2.useCallback(async () => {
1603
- const wallet = walletRef.current;
1604
- if (!wallet || state.status !== "connected") return;
1605
- try {
1606
- const balance = await wallet.getBalance();
1607
- if (mountedRef.current) {
1608
- dispatch({ type: "SET_BALANCE", balance });
1609
- }
1610
- } catch {
1611
- }
1612
- }, [state.status]);
1613
- const switchNetwork = React2.useCallback(async (network) => {
1614
- const wallet = walletRef.current;
1615
- if (!wallet) return;
1616
- await wallet.switchNetwork(network);
1617
- if (mountedRef.current) {
1618
- dispatch({ type: "SET_NETWORK", network });
1619
- onNetworkChange?.(network);
1620
- }
1621
- }, [onNetworkChange]);
1622
- const signMessage = React2.useCallback(async (message) => {
1623
- const wallet = walletRef.current;
1624
- if (!wallet || state.status !== "connected") throw new Error("Wallet not connected");
1625
- return wallet.signMessage(message);
1626
- }, [state.status]);
1627
- const signTransaction = React2.useCallback(async (tx) => {
1628
- const wallet = walletRef.current;
1629
- if (!wallet || state.status !== "connected") throw new Error("Wallet not connected");
1630
- return wallet.signTransaction(tx);
1631
- }, [state.status]);
1632
- const sendTransaction = React2.useCallback(async (tx) => {
1633
- const wallet = walletRef.current;
1634
- if (!wallet || state.status !== "connected") throw new Error("Wallet not connected");
1635
- return wallet.sendTransaction(tx);
1636
- }, [state.status]);
1637
- const signAndSendTransaction = React2.useCallback(async (tx) => {
1638
- const wallet = walletRef.current;
1639
- if (!wallet || state.status !== "connected") throw new Error("Wallet not connected");
1640
- return wallet.signAndSendTransaction(tx);
1641
- }, [state.status]);
1642
- const getREXCapabilities = React2.useCallback(async () => {
1643
- const wallet = walletRef.current;
1644
- if (!wallet) return { supported: false, privacyModes: [], maxInputSize: 0, programs: [] };
1645
- return wallet.getREXCapabilities();
1646
- }, []);
1647
- const submitREXTransaction = React2.useCallback(async (tx) => {
1648
- const wallet = walletRef.current;
1649
- if (!wallet || state.status !== "connected") throw new Error("Wallet not connected");
1650
- return wallet.submitREXTransaction(tx);
1651
- }, [state.status]);
1652
- const sendGaslessTransaction = React2.useCallback(async (tx) => {
1653
- const wallet = walletRef.current;
1654
- if (!wallet || state.status !== "connected") throw new Error("Wallet not connected");
1655
- return wallet.sendGaslessTransaction(tx);
1656
- }, [state.status]);
1657
- const getSfSPositions = React2.useCallback(async () => {
1658
- const wallet = walletRef.current;
1659
- if (!wallet || state.status !== "connected") return [];
1660
- return wallet.getSfSPositions();
1661
- }, [state.status]);
1662
- const createSfSPosition = React2.useCallback(async (params) => {
1663
- const wallet = walletRef.current;
1664
- if (!wallet || state.status !== "connected") throw new Error("Wallet not connected");
1665
- return wallet.createSfSPosition(params);
1666
- }, [state.status]);
1667
- const getSfSCredits = React2.useCallback(async () => {
1668
- const wallet = walletRef.current;
1669
- if (!wallet || state.status !== "connected") {
1670
- return { available: "0", usedThisEpoch: "0", totalEarned: "0", estimatedPerEpoch: "0" };
1671
- }
1672
- return wallet.getSfSCredits();
1673
- }, [state.status]);
1674
- const openModal = React2.useCallback(() => dispatch({ type: "OPEN_MODAL" }), []);
1675
- const closeModal = React2.useCallback(() => dispatch({ type: "CLOSE_MODAL" }), []);
1676
- const wallets = React2.useMemo(() => {
1677
- const extensionInstalled = isInstalled();
1678
- return [...DEFAULT_WALLETS, ...customWallets].map((w) => ({
1679
- ...w,
1680
- installed: w.id === "sheep-wallet" ? extensionInstalled : false
1681
- }));
1682
- }, [customWallets]);
1683
- const value = React2.useMemo(() => ({
1684
- state,
1685
- connected: state.status === "connected",
1686
- connecting: state.status === "connecting",
1687
- activeAccount: state.accounts[0] || null,
1688
- chainId: `rialo:${state.network}`,
1689
- isInstalled: isInstalled(),
1690
- wallets,
1691
- connect,
1692
- disconnect,
1693
- refreshBalance,
1694
- switchNetwork,
1695
- signMessage,
1696
- signTransaction,
1697
- sendTransaction,
1698
- signAndSendTransaction,
1699
- getREXCapabilities,
1700
- submitREXTransaction,
1701
- sendGaslessTransaction,
1702
- getSfSPositions,
1703
- createSfSPosition,
1704
- getSfSCredits,
1705
- openModal,
1706
- closeModal,
1707
- wallet: walletRef.current
1708
- }), [
1709
- state,
1710
- wallets,
1711
- connect,
1712
- disconnect,
1713
- refreshBalance,
1714
- switchNetwork,
1715
- signMessage,
1716
- signTransaction,
1717
- sendTransaction,
1718
- signAndSendTransaction,
1719
- getREXCapabilities,
1720
- submitREXTransaction,
1721
- sendGaslessTransaction,
1722
- getSfSPositions,
1723
- createSfSPosition,
1724
- getSfSCredits,
1725
- openModal,
1726
- closeModal
1727
- ]);
1728
- return /* @__PURE__ */ jsxRuntime.jsxs(WalletContext.Provider, { value, children: [
1729
- children,
1730
- /* @__PURE__ */ jsxRuntime.jsx(WalletModal, { scanConnectRelay })
1731
- ] });
1732
- }
1733
- function useWallet() {
1734
- const context = React2.useContext(WalletContext);
1735
- if (!context) {
1736
- throw new Error("useWallet must be used within WalletProvider");
1737
- }
1738
- return context;
1739
- }
1740
- function useIsConnected() {
1741
- return useWallet().connected;
1742
- }
1743
- function useActiveAccount() {
1744
- return useWallet().activeAccount;
1745
- }
1746
- function useAccounts() {
1747
- return useWallet().state.accounts;
1748
- }
1749
- function useBalance() {
1750
- const { state, refreshBalance } = useWallet();
1751
- return { balance: state.balance, refresh: refreshBalance };
1752
- }
1753
- function useNetwork() {
1754
- const { state, chainId } = useWallet();
1755
- return { network: state.network, chainId };
1756
- }
1757
- function useSwitchNetwork() {
1758
- const { switchNetwork, state } = useWallet();
1759
- return { switchNetwork, network: state.network };
1760
- }
1761
- function useConnectWallet() {
1762
- const { connect, openModal, connecting, connected, isInstalled: isInstalled2, state } = useWallet();
1763
- return { connect, openModal, connecting, connected, isInstalled: isInstalled2, error: state.error };
1764
- }
1765
- function useDisconnectWallet() {
1766
- const { disconnect, connected } = useWallet();
1767
- return { disconnect, connected };
1768
- }
1769
- function useSignMessage() {
1770
- const { signMessage, connected } = useWallet();
1771
- return { signMessage, connected };
1772
- }
1773
- function useSendTransaction() {
1774
- const { sendTransaction, signAndSendTransaction, sendGaslessTransaction, connected } = useWallet();
1775
- return { sendTransaction, signAndSendTransaction, sendGaslessTransaction, connected };
1776
- }
1777
- function useREX() {
1778
- const { getREXCapabilities, submitREXTransaction, connected } = useWallet();
1779
- const [capabilities, setCapabilities] = React2.useState(null);
1780
- React2.useEffect(() => {
1781
- if (connected) {
1782
- getREXCapabilities().then(setCapabilities).catch(() => {
1783
- });
1784
- }
1785
- }, [connected, getREXCapabilities]);
1786
- return {
1787
- capabilities,
1788
- supported: capabilities?.supported ?? false,
1789
- submitREXTransaction,
1790
- connected
1791
- };
1792
- }
1793
- function useSfS() {
1794
- const { getSfSPositions, createSfSPosition, getSfSCredits, sendGaslessTransaction, connected } = useWallet();
1795
- const [positions, setPositions] = React2.useState([]);
1796
- const [credits, setCredits] = React2.useState(null);
1797
- const refresh = React2.useCallback(async () => {
1798
- if (!connected) return;
1799
- const [pos, cred] = await Promise.all([
1800
- getSfSPositions().catch(() => []),
1801
- getSfSCredits().catch(() => null)
1802
- ]);
1803
- setPositions(pos);
1804
- if (cred) setCredits(cred);
1805
- }, [connected, getSfSPositions, getSfSCredits]);
1806
- React2.useEffect(() => {
1807
- refresh();
1808
- }, [refresh]);
1809
- return {
1810
- positions,
1811
- credits,
1812
- hasCredits: BigInt(credits?.available ?? "0") > 0n,
1813
- createPosition: createSfSPosition,
1814
- sendGasless: sendGaslessTransaction,
1815
- refresh,
1816
- connected
1817
- };
1818
- }
1819
- function useScanConnect() {
1820
- const { wallet, state } = useWallet();
1821
- const [scanURI, setScanURI] = React2.useState(null);
1822
- const [status, setStatus] = React2.useState("idle");
1823
- const generateQR = React2.useCallback(async () => {
1824
- if (!wallet) return;
1825
- setStatus("generating");
1826
- try {
1827
- const uri = await wallet.createScanSession();
1828
- setScanURI(uri);
1829
- setStatus("waiting");
1830
- } catch (error) {
1831
- setStatus("error");
1832
- }
1833
- }, [wallet]);
1834
- const approveSession = React2.useCallback(async (sessionId) => {
1835
- if (!wallet) return [];
1836
- setStatus("approving");
1837
- try {
1838
- const accounts = await wallet.approveScanSession(sessionId);
1839
- setStatus("connected");
1840
- return accounts;
1841
- } catch {
1842
- setStatus("error");
1843
- return [];
1844
- }
1845
- }, [wallet]);
1846
- const rejectSession = React2.useCallback(async (sessionId) => {
1847
- if (!wallet) return;
1848
- await wallet.rejectScanSession(sessionId);
1849
- setStatus("rejected");
1850
- }, [wallet]);
1851
- return {
1852
- scanURI,
1853
- status,
1854
- generateQR,
1855
- approveSession,
1856
- rejectSession
1857
- };
1858
- }
1859
- function ConnectButton({
1860
- connectLabel = "Connect Wallet",
1861
- disconnectLabel = "Disconnect",
1862
- showAddress = true,
1863
- showBalance = false,
1864
- showFeatures = false,
1865
- className,
1866
- style
1867
- }) {
1868
- const { connected, connecting, connect, disconnect, activeAccount, state, openModal, isInstalled: installed } = useWallet();
1869
- const [showMenu, setShowMenu] = React2__default.default.useState(false);
1870
- const handleClick = async () => {
1871
- if (connected) {
1872
- setShowMenu(!showMenu);
1873
- } else {
1874
- openModal();
1875
- }
1876
- };
1877
- const displayText = connected && activeAccount && showAddress ? `${activeAccount.address.slice(0, 6)}...${activeAccount.address.slice(-4)}` : connecting ? "Connecting..." : connectLabel;
1878
- const defaultStyle = {
1879
- padding: "12px 20px",
1880
- borderRadius: "12px",
1881
- border: "none",
1882
- cursor: connecting ? "wait" : "pointer",
1883
- fontWeight: 500,
1884
- fontSize: "14px",
1885
- backgroundColor: connected ? "#1a3a4d" : "#6EB9A8",
1886
- color: connected ? "#ffffff" : "#011B29",
1887
- transition: "all 0.2s",
1888
- position: "relative",
1889
- ...style
1890
- };
1891
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative", display: "inline-block" }, children: [
1892
- /* @__PURE__ */ jsxRuntime.jsxs(
1893
- "button",
1894
- {
1895
- onClick: handleClick,
1896
- disabled: connecting,
1897
- className,
1898
- style: defaultStyle,
1899
- children: [
1900
- displayText,
1901
- showBalance && state.balance && /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { marginLeft: "8px", opacity: 0.8 }, children: [
1902
- (Number(state.balance) / 1e9).toFixed(2),
1903
- " RLO"
1904
- ] })
1905
- ]
1906
- }
1907
- ),
1908
- connected && showMenu && /* @__PURE__ */ jsxRuntime.jsxs(
1909
- "div",
1910
- {
1911
- style: {
1912
- position: "absolute",
1913
- top: "100%",
1914
- right: 0,
1915
- marginTop: "8px",
1916
- backgroundColor: "#011B29",
1917
- borderRadius: "12px",
1918
- padding: "8px",
1919
- minWidth: "180px",
1920
- boxShadow: "0 10px 40px rgba(0, 0, 0, 0.3)",
1921
- zIndex: 100,
1922
- border: "1px solid #2a4a5d"
1923
- },
1924
- children: [
1925
- activeAccount && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
1926
- padding: "8px 12px",
1927
- borderBottom: "1px solid #1a3a4d",
1928
- marginBottom: "4px"
1929
- }, children: [
1930
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#94a3b8", fontSize: "10px", marginBottom: "4px" }, children: "Connected" }),
1931
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#ffffff", fontSize: "12px", fontFamily: "monospace" }, children: formatAddress(activeAccount.address, 8) })
1932
- ] }),
1933
- showFeatures && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
1934
- padding: "6px 12px",
1935
- display: "flex",
1936
- gap: "6px",
1937
- borderBottom: "1px solid #1a3a4d",
1938
- marginBottom: "4px"
1939
- }, children: [
1940
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "10px", color: "#8B5CF6", backgroundColor: "#8B5CF615", padding: "2px 6px", borderRadius: "4px" }, children: "REX" }),
1941
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "10px", color: "#F59E0B", backgroundColor: "#F59E0B15", padding: "2px 6px", borderRadius: "4px" }, children: "SfS" })
1942
- ] }),
1943
- /* @__PURE__ */ jsxRuntime.jsx(
1944
- "button",
1945
- {
1946
- onClick: () => {
1947
- setShowMenu(false);
1948
- disconnect();
1949
- },
1950
- style: {
1951
- width: "100%",
1952
- padding: "10px 12px",
1953
- backgroundColor: "transparent",
1954
- border: "none",
1955
- borderRadius: "8px",
1956
- color: "#ef4444",
1957
- cursor: "pointer",
1958
- textAlign: "left",
1959
- fontSize: "13px"
1960
- },
1961
- children: disconnectLabel
1962
- }
1963
- )
1964
- ]
1965
- }
1966
- )
1967
- ] });
1968
- }
1969
- var WalletErrorBoundary = class extends React2.Component {
1970
- constructor(props) {
1971
- super(props);
1972
- this.handleReset = () => {
1973
- this.setState({ hasError: false, error: null });
1974
- };
1975
- this.state = { hasError: false, error: null };
1976
- }
1977
- static getDerivedStateFromError(error) {
1978
- return { hasError: true, error };
1979
- }
1980
- componentDidCatch(error, errorInfo) {
1981
- console.error("[WalletErrorBoundary] Caught error:", error, errorInfo);
1982
- this.props.onError?.(error, errorInfo);
1983
- }
1984
- render() {
1985
- if (this.state.hasError && this.state.error) {
1986
- const { fallback } = this.props;
1987
- if (typeof fallback === "function") {
1988
- return fallback(this.state.error, this.handleReset);
1989
- }
1990
- if (fallback) {
1991
- return fallback;
1992
- }
1993
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
1994
- padding: "20px",
1995
- margin: "10px",
1996
- backgroundColor: "#1a1a2e",
1997
- border: "1px solid #ef4444",
1998
- borderRadius: "12px",
1999
- color: "#ffffff"
2000
- }, children: [
2001
- /* @__PURE__ */ jsxRuntime.jsx("h3", { style: { color: "#ef4444", margin: "0 0 12px 0" }, children: "Wallet Connection Error" }),
2002
- /* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: "#94a3b8", margin: "0 0 16px 0", fontSize: "14px" }, children: this.state.error.message }),
2003
- /* @__PURE__ */ jsxRuntime.jsx(
2004
- "button",
2005
- {
2006
- onClick: this.handleReset,
2007
- style: {
2008
- padding: "8px 16px",
2009
- backgroundColor: "#6EB9A8",
2010
- color: "#011B29",
2011
- border: "none",
2012
- borderRadius: "8px",
2013
- cursor: "pointer",
2014
- fontWeight: 500
2015
- },
2016
- children: "Try Again"
2017
- }
2018
- )
2019
- ] });
2020
- }
2021
- return this.props.children;
2022
- }
2023
- };
2024
- function withWalletErrorBoundary(WrappedComponent, fallback) {
2025
- return function WithErrorBoundary(props) {
2026
- return /* @__PURE__ */ jsxRuntime.jsx(WalletErrorBoundary, { fallback, children: /* @__PURE__ */ jsxRuntime.jsx(WrappedComponent, { ...props }) });
2027
- };
2028
- }
2029
- function LoadingSpinner({
2030
- size = "md",
2031
- color = "#6EB9A8",
2032
- className
2033
- }) {
2034
- const sizeMap = { sm: 16, md: 24, lg: 32 };
2035
- const px = sizeMap[size];
2036
- return /* @__PURE__ */ jsxRuntime.jsxs(
2037
- "svg",
2038
- {
2039
- className,
2040
- width: px,
2041
- height: px,
2042
- viewBox: "0 0 24 24",
2043
- fill: "none",
2044
- style: { animation: "spin 1s linear infinite" },
2045
- children: [
2046
- /* @__PURE__ */ jsxRuntime.jsx("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` }),
2047
- /* @__PURE__ */ jsxRuntime.jsx(
2048
- "circle",
2049
- {
2050
- cx: "12",
2051
- cy: "12",
2052
- r: "10",
2053
- stroke: color,
2054
- strokeWidth: "2.5",
2055
- fill: "none",
2056
- strokeDasharray: "50 20",
2057
- strokeLinecap: "round"
2058
- }
2059
- )
2060
- ]
2061
- }
2062
- );
2063
- }
2064
- function ConnectionStatus({ status, message, onRetry }) {
2065
- const configs = {
2066
- idle: { color: "#64748b", label: "Ready" },
2067
- connecting: { color: "#6EB9A8", label: "Connecting..." },
2068
- approving: { color: "#f59e0b", label: "Waiting for approval..." },
2069
- signing: { color: "#6EB9A8", label: "Signing..." },
2070
- success: { color: "#22c55e", label: "Connected" },
2071
- error: { color: "#ef4444", label: "Error" }
2072
- };
2073
- const config = configs[status];
2074
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
2075
- display: "flex",
2076
- alignItems: "center",
2077
- gap: "12px",
2078
- padding: "12px 16px",
2079
- backgroundColor: `${config.color}15`,
2080
- borderRadius: "10px",
2081
- border: `1px solid ${config.color}30`
2082
- }, children: [
2083
- (status === "connecting" || status === "approving" || status === "signing") && /* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, { size: "sm", color: config.color }),
2084
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1 }, children: [
2085
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: config.color, fontWeight: 500, fontSize: "14px" }, children: config.label }),
2086
- message && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#94a3b8", fontSize: "12px", marginTop: "2px" }, children: message })
2087
- ] }),
2088
- status === "error" && onRetry && /* @__PURE__ */ jsxRuntime.jsx(
2089
- "button",
2090
- {
2091
- onClick: onRetry,
2092
- style: {
2093
- padding: "6px 12px",
2094
- backgroundColor: config.color,
2095
- color: "#ffffff",
2096
- border: "none",
2097
- borderRadius: "6px",
2098
- cursor: "pointer",
2099
- fontSize: "12px",
2100
- fontWeight: 500
2101
- },
2102
- children: "Retry"
2103
- }
2104
- )
2105
- ] });
2106
- }
2107
- function ApprovalPending({
2108
- title = "Waiting for Approval",
2109
- message = "Please approve the request in your wallet",
2110
- walletName = "Sheep Wallet",
2111
- onCancel
2112
- }) {
2113
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
2114
- textAlign: "center",
2115
- padding: "32px 24px"
2116
- }, children: [
2117
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
2118
- width: "64px",
2119
- height: "64px",
2120
- margin: "0 auto 20px",
2121
- borderRadius: "16px",
2122
- backgroundColor: "#6EB9A815",
2123
- display: "flex",
2124
- alignItems: "center",
2125
- justifyContent: "center",
2126
- animation: "pulse 2s ease-in-out infinite"
2127
- }, children: [
2128
- /* @__PURE__ */ jsxRuntime.jsx("style", { children: `
2129
- @keyframes pulse {
2130
- 0%, 100% { transform: scale(1); opacity: 1; }
2131
- 50% { transform: scale(1.05); opacity: 0.8; }
2132
- }
2133
- ` }),
2134
- /* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, { size: "lg" })
2135
- ] }),
2136
- /* @__PURE__ */ jsxRuntime.jsx("h3", { style: {
2137
- color: "#ffffff",
2138
- margin: "0 0 8px 0",
2139
- fontSize: "18px",
2140
- fontWeight: 600
2141
- }, children: title }),
2142
- /* @__PURE__ */ jsxRuntime.jsx("p", { style: {
2143
- color: "#94a3b8",
2144
- margin: "0 0 24px 0",
2145
- fontSize: "14px"
2146
- }, children: message }),
2147
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
2148
- padding: "12px 16px",
2149
- backgroundColor: "#1a3a4d",
2150
- borderRadius: "10px",
2151
- color: "#6EB9A8",
2152
- fontSize: "13px",
2153
- marginBottom: "20px"
2154
- }, children: [
2155
- "Check ",
2156
- walletName,
2157
- " extension"
2158
- ] }),
2159
- onCancel && /* @__PURE__ */ jsxRuntime.jsx(
2160
- "button",
2161
- {
2162
- onClick: onCancel,
2163
- style: {
2164
- padding: "10px 24px",
2165
- backgroundColor: "transparent",
2166
- border: "1px solid #374151",
2167
- borderRadius: "8px",
2168
- color: "#9ca3af",
2169
- cursor: "pointer",
2170
- fontSize: "14px"
2171
- },
2172
- children: "Cancel"
2173
- }
2174
- )
2175
- ] });
2176
- }
2177
333
 
2178
- exports.ApprovalPending = ApprovalPending;
2179
- exports.ConnectButton = ConnectButton;
2180
- exports.ConnectionStatus = ConnectionStatus;
2181
- exports.LoadingSpinner = LoadingSpinner;
2182
334
  exports.NETWORKS = NETWORKS;
2183
335
  exports.SheepWallet = SheepWallet;
2184
- exports.WalletErrorBoundary = WalletErrorBoundary;
2185
- exports.WalletModal = WalletModal;
2186
- exports.WalletProvider = WalletProvider;
2187
336
  exports.formatAddress = formatAddress;
2188
337
  exports.formatBalance = formatBalance;
2189
338
  exports.isInstalled = isInstalled;
2190
339
  exports.isValidAddress = isValidAddress;
2191
340
  exports.parseBalance = parseBalance;
2192
- exports.useAccounts = useAccounts;
2193
- exports.useActiveAccount = useActiveAccount;
2194
- exports.useBalance = useBalance;
2195
- exports.useConnectWallet = useConnectWallet;
2196
- exports.useDisconnectWallet = useDisconnectWallet;
2197
- exports.useIsConnected = useIsConnected;
2198
- exports.useNetwork = useNetwork;
2199
- exports.useREX = useREX;
2200
- exports.useScanConnect = useScanConnect;
2201
- exports.useSendTransaction = useSendTransaction;
2202
- exports.useSfS = useSfS;
2203
- exports.useSignMessage = useSignMessage;
2204
- exports.useSwitchNetwork = useSwitchNetwork;
2205
- exports.useWallet = useWallet;
2206
- exports.withWalletErrorBoundary = withWalletErrorBoundary;
2207
341
  //# sourceMappingURL=react.cjs.map
2208
342
  //# sourceMappingURL=react.cjs.map