cosmos-connect-react 0.1.1 → 0.1.3
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/hooks.d.ts +6 -6
- package/package.json +6 -2
- package/src/CosmosProvider.tsx +0 -75
- package/src/components/Avatar.tsx +0 -51
- package/src/components/ConnectButton.tsx +0 -44
- package/src/components/ConnectModal.tsx +0 -138
- package/src/components/Pages/About.tsx +0 -37
- package/src/components/Pages/Connecting.tsx +0 -30
- package/src/components/Pages/Connectors.tsx +0 -30
- package/src/components/Pages/Profile.tsx +0 -66
- package/src/hooks.ts +0 -73
- package/src/index.ts +0 -6
- package/tsconfig.json +0 -16
- /package/{src → dist}/styles.css +0 -0
package/dist/hooks.d.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
export declare const useAccount: () => {
|
|
2
|
-
address:
|
|
3
|
-
status:
|
|
2
|
+
address: string | undefined;
|
|
3
|
+
status: import("cosmos-connect-core").ClientStatus;
|
|
4
4
|
isConnected: boolean;
|
|
5
5
|
isConnecting: boolean;
|
|
6
6
|
isDisconnected: boolean;
|
|
7
|
-
account:
|
|
7
|
+
account: import("cosmos-connect-core").Account | null;
|
|
8
8
|
};
|
|
9
9
|
export declare const useConnect: () => {
|
|
10
|
-
connect: (walletId: string, chainId: string) => Promise<
|
|
10
|
+
connect: (walletId: string, chainId: string) => Promise<void>;
|
|
11
11
|
};
|
|
12
12
|
export declare const useDisconnect: () => {
|
|
13
|
-
disconnect: () => Promise<
|
|
13
|
+
disconnect: () => Promise<void>;
|
|
14
14
|
};
|
|
15
|
-
export declare const useClient: () => Client;
|
|
15
|
+
export declare const useClient: () => import("cosmos-connect-core").Client;
|
|
16
16
|
export declare const useBalance: () => {
|
|
17
17
|
balance: {
|
|
18
18
|
amount: string;
|
package/package.json
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cosmos-connect-react",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"type": "module",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist",
|
|
9
|
+
"README.md"
|
|
10
|
+
],
|
|
7
11
|
"scripts": {
|
|
8
|
-
"build": "tsc"
|
|
12
|
+
"build": "tsc && cp src/styles.css dist/"
|
|
9
13
|
},
|
|
10
14
|
"peerDependencies": {
|
|
11
15
|
"cosmos-connect-core": "*",
|
package/src/CosmosProvider.tsx
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
createContext,
|
|
3
|
-
useContext,
|
|
4
|
-
useEffect,
|
|
5
|
-
useState,
|
|
6
|
-
ReactNode,
|
|
7
|
-
} from 'react';
|
|
8
|
-
import {
|
|
9
|
-
Client,
|
|
10
|
-
ClientState,
|
|
11
|
-
createClient,
|
|
12
|
-
ClientConfig,
|
|
13
|
-
TERRA_CLASSIC,
|
|
14
|
-
KeplrWallet,
|
|
15
|
-
GalaxyStationWallet,
|
|
16
|
-
LeapWallet,
|
|
17
|
-
WalletConnectWallet,
|
|
18
|
-
} from 'cosmos-connect-core';
|
|
19
|
-
|
|
20
|
-
interface CosmosContextValue {
|
|
21
|
-
client: Client;
|
|
22
|
-
state: ClientState;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const CosmosContext = createContext<CosmosContextValue | null>(null);
|
|
26
|
-
|
|
27
|
-
const DEFAULT_CONFIG: ClientConfig = {
|
|
28
|
-
chains: [TERRA_CLASSIC],
|
|
29
|
-
wallets: [
|
|
30
|
-
new GalaxyStationWallet(),
|
|
31
|
-
new KeplrWallet(),
|
|
32
|
-
new LeapWallet(),
|
|
33
|
-
new WalletConnectWallet({
|
|
34
|
-
projectId: '39190b939e067ecb6dccdb7c77653a42', // Default placeholder or instructions needed
|
|
35
|
-
}),
|
|
36
|
-
],
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
export interface CosmosProviderProps {
|
|
40
|
-
children: ReactNode;
|
|
41
|
-
config?: Partial<ClientConfig>;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export const CosmosProvider: React.FC<CosmosProviderProps> = ({
|
|
45
|
-
children,
|
|
46
|
-
config,
|
|
47
|
-
}) => {
|
|
48
|
-
const [client] = useState(() => {
|
|
49
|
-
const fullConfig: ClientConfig = {
|
|
50
|
-
chains: config?.chains || DEFAULT_CONFIG.chains,
|
|
51
|
-
wallets: config?.wallets || DEFAULT_CONFIG.wallets,
|
|
52
|
-
storage: config?.storage || DEFAULT_CONFIG.storage,
|
|
53
|
-
};
|
|
54
|
-
return createClient(fullConfig);
|
|
55
|
-
});
|
|
56
|
-
const [state, setState] = useState<ClientState>(client.state);
|
|
57
|
-
|
|
58
|
-
useEffect(() => {
|
|
59
|
-
return client.subscribe(setState);
|
|
60
|
-
}, [client]);
|
|
61
|
-
|
|
62
|
-
return (
|
|
63
|
-
<CosmosContext.Provider value={{ client, state }}>
|
|
64
|
-
{children}
|
|
65
|
-
</CosmosContext.Provider>
|
|
66
|
-
);
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
export const useCosmos = () => {
|
|
70
|
-
const context = useContext(CosmosContext);
|
|
71
|
-
if (!context) {
|
|
72
|
-
throw new Error('useCosmos must be used within a CosmosProvider');
|
|
73
|
-
}
|
|
74
|
-
return context;
|
|
75
|
-
};
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
|
-
interface AvatarProps {
|
|
4
|
-
address: string;
|
|
5
|
-
size?: number;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* A simple, colorful avatar generated from the address.
|
|
10
|
-
* Mimics the ConnectKit/RainbowKit feel.
|
|
11
|
-
*/
|
|
12
|
-
export const Avatar: React.FC<AvatarProps> = ({ address, size = 32 }) => {
|
|
13
|
-
// Simple deterministic color generation from address
|
|
14
|
-
const colors = [
|
|
15
|
-
'#FFADAD', '#FFD6A5', '#FDFFB6', '#CAFFBF',
|
|
16
|
-
'#9BF6FF', '#A0C4FF', '#BDB2FF', '#FFC6FF'
|
|
17
|
-
];
|
|
18
|
-
|
|
19
|
-
const getHash = (str: string) => {
|
|
20
|
-
let hash = 0;
|
|
21
|
-
for (let i = 0; i < str.length; i++) {
|
|
22
|
-
hash = str.charCodeAt(i) + ((hash << 5) - hash);
|
|
23
|
-
}
|
|
24
|
-
return hash;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const colorIndex = Math.abs(getHash(address)) % colors.length;
|
|
28
|
-
const secondaryColorIndex = (colorIndex + 3) % colors.length;
|
|
29
|
-
|
|
30
|
-
return (
|
|
31
|
-
<div
|
|
32
|
-
style={{
|
|
33
|
-
width: size,
|
|
34
|
-
height: size,
|
|
35
|
-
borderRadius: '50%',
|
|
36
|
-
background: `linear-gradient(135deg, ${colors[colorIndex]} 0%, ${colors[secondaryColorIndex]} 100%)`,
|
|
37
|
-
display: 'flex',
|
|
38
|
-
alignItems: 'center',
|
|
39
|
-
justifyContent: 'center',
|
|
40
|
-
fontSize: size * 0.4,
|
|
41
|
-
fontWeight: 'bold',
|
|
42
|
-
color: 'white',
|
|
43
|
-
textShadow: '0 1px 2px rgba(0,0,0,0.1)',
|
|
44
|
-
flexShrink: 0,
|
|
45
|
-
overflow: 'hidden'
|
|
46
|
-
}}
|
|
47
|
-
>
|
|
48
|
-
{address.slice(-2).toUpperCase()}
|
|
49
|
-
</div>
|
|
50
|
-
);
|
|
51
|
-
};
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import React, { useState } from 'react';
|
|
2
|
-
import { useAccount } from '../hooks.js';
|
|
3
|
-
import { ConnectModal } from './ConnectModal.js';
|
|
4
|
-
import { Avatar } from './Avatar.js';
|
|
5
|
-
|
|
6
|
-
export const ConnectButton: React.FC = () => {
|
|
7
|
-
const { isConnected, address, status } = useAccount();
|
|
8
|
-
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
9
|
-
|
|
10
|
-
const formatAddress = (addr: string) => {
|
|
11
|
-
return `${addr.slice(0, 8)}...${addr.slice(-4)}`;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
if (isConnected && address) {
|
|
15
|
-
return (
|
|
16
|
-
<>
|
|
17
|
-
<button className="cc-pill" onClick={() => setIsModalOpen(true)}>
|
|
18
|
-
<Avatar address={address} size={24} />
|
|
19
|
-
<span className="cc-pill-text">{formatAddress(address)}</span>
|
|
20
|
-
</button>
|
|
21
|
-
<ConnectModal
|
|
22
|
-
isOpen={isModalOpen}
|
|
23
|
-
onClose={() => setIsModalOpen(false)}
|
|
24
|
-
/>
|
|
25
|
-
</>
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return (
|
|
30
|
-
<>
|
|
31
|
-
<button
|
|
32
|
-
className="cc-btn"
|
|
33
|
-
onClick={() => setIsModalOpen(true)}
|
|
34
|
-
disabled={status === 'connecting'}
|
|
35
|
-
>
|
|
36
|
-
{status === 'connecting' ? 'Connecting...' : 'Connect Wallet'}
|
|
37
|
-
</button>
|
|
38
|
-
<ConnectModal
|
|
39
|
-
isOpen={isModalOpen}
|
|
40
|
-
onClose={() => setIsModalOpen(false)}
|
|
41
|
-
/>
|
|
42
|
-
</>
|
|
43
|
-
);
|
|
44
|
-
};
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import React, { useState, useEffect } from 'react';
|
|
2
|
-
import { AnimatePresence, motion } from 'framer-motion';
|
|
3
|
-
import { useCosmos } from '../CosmosProvider.js';
|
|
4
|
-
import { useConnect, useAccount } from '../hooks.js';
|
|
5
|
-
|
|
6
|
-
import Connectors from './Pages/Connectors.js';
|
|
7
|
-
import About from './Pages/About.js';
|
|
8
|
-
import Profile from './Pages/Profile.js';
|
|
9
|
-
import Connecting from './Pages/Connecting.js';
|
|
10
|
-
|
|
11
|
-
interface ConnectModalProps {
|
|
12
|
-
isOpen: boolean;
|
|
13
|
-
onClose: () => void;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export type ModalRoute = 'connectors' | 'about' | 'profile' | 'connecting';
|
|
17
|
-
|
|
18
|
-
export const ConnectModal: React.FC<ConnectModalProps> = ({ isOpen, onClose }) => {
|
|
19
|
-
const { client } = useCosmos();
|
|
20
|
-
const { connect } = useConnect();
|
|
21
|
-
const { isConnected, status } = useAccount();
|
|
22
|
-
|
|
23
|
-
const [route, setRoute] = useState<ModalRoute>('connectors');
|
|
24
|
-
const [pendingWallet, setPendingWallet] = useState<any>(null);
|
|
25
|
-
|
|
26
|
-
// Sync route with connection status
|
|
27
|
-
useEffect(() => {
|
|
28
|
-
if (isConnected) {
|
|
29
|
-
setRoute('profile');
|
|
30
|
-
} else if (status === 'connecting') {
|
|
31
|
-
setRoute('connecting');
|
|
32
|
-
} else if (!isOpen) {
|
|
33
|
-
setRoute('connectors');
|
|
34
|
-
}
|
|
35
|
-
}, [isConnected, status, isOpen]);
|
|
36
|
-
|
|
37
|
-
if (!isOpen) return null;
|
|
38
|
-
|
|
39
|
-
const handleWalletSelect = async (wallet: any) => {
|
|
40
|
-
try {
|
|
41
|
-
setPendingWallet(wallet);
|
|
42
|
-
setRoute('connecting');
|
|
43
|
-
const chainId = client.getChains()[0]?.chainId || 'columbus-5';
|
|
44
|
-
await connect(wallet.id, chainId);
|
|
45
|
-
} catch (error) {
|
|
46
|
-
console.error('Failed to connect:', error);
|
|
47
|
-
setRoute('connectors');
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
const showBackButton = route !== 'connectors' && route !== 'profile';
|
|
52
|
-
const showInfoButton = route === 'connectors';
|
|
53
|
-
|
|
54
|
-
const variants = {
|
|
55
|
-
initial: (direction: number) => ({
|
|
56
|
-
x: direction > 0 ? 50 : -50,
|
|
57
|
-
opacity: 0,
|
|
58
|
-
}),
|
|
59
|
-
animate: {
|
|
60
|
-
x: 0,
|
|
61
|
-
opacity: 1,
|
|
62
|
-
},
|
|
63
|
-
exit: (direction: number) => ({
|
|
64
|
-
x: direction < 0 ? 50 : -50,
|
|
65
|
-
opacity: 0,
|
|
66
|
-
}),
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
// Direction logic for transitions (simple for now)
|
|
70
|
-
const getDirection = (newRoute: ModalRoute) => {
|
|
71
|
-
if (newRoute === 'about' || newRoute === 'connecting') return 1;
|
|
72
|
-
return -1;
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
const renderPage = () => {
|
|
76
|
-
switch (route) {
|
|
77
|
-
case 'connectors':
|
|
78
|
-
return <Connectors onSelect={handleWalletSelect} />;
|
|
79
|
-
case 'about':
|
|
80
|
-
return <About />;
|
|
81
|
-
case 'profile':
|
|
82
|
-
return <Profile />;
|
|
83
|
-
case 'connecting':
|
|
84
|
-
return <Connecting wallet={pendingWallet} onCancel={() => setRoute('connectors')} />;
|
|
85
|
-
default:
|
|
86
|
-
return null;
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
const getTitle = () => {
|
|
91
|
-
switch (route) {
|
|
92
|
-
case 'profile': return 'Account';
|
|
93
|
-
case 'about': return 'About Wallets';
|
|
94
|
-
case 'connecting': return 'Requesting Connection';
|
|
95
|
-
default: return 'Connect Wallet';
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
return (
|
|
100
|
-
<div className="cc-modal-overlay" onClick={onClose}>
|
|
101
|
-
<motion.div
|
|
102
|
-
className="cc-modal-content"
|
|
103
|
-
onClick={(e) => e.stopPropagation()}
|
|
104
|
-
initial={{ scale: 0.95, opacity: 0 }}
|
|
105
|
-
animate={{ scale: 1, opacity: 1 }}
|
|
106
|
-
exit={{ scale: 0.95, opacity: 0 }}
|
|
107
|
-
>
|
|
108
|
-
<div className="cc-modal-header">
|
|
109
|
-
{showBackButton ? (
|
|
110
|
-
<button className="cc-back-btn" onClick={() => setRoute('connectors')}>←</button>
|
|
111
|
-
) : showInfoButton ? (
|
|
112
|
-
<button className="cc-help-btn" onClick={() => setRoute('about')} title="About Wallets">?</button>
|
|
113
|
-
) : <div style={{ width: 28 }} />}
|
|
114
|
-
|
|
115
|
-
<span className="cc-modal-title">{getTitle()}</span>
|
|
116
|
-
|
|
117
|
-
<button className="cc-close-btn" onClick={onClose}>×</button>
|
|
118
|
-
</div>
|
|
119
|
-
|
|
120
|
-
<div className="cc-modal-body">
|
|
121
|
-
<AnimatePresence exitBeforeEnter initial={false}>
|
|
122
|
-
<motion.div
|
|
123
|
-
key={route}
|
|
124
|
-
custom={getDirection(route)}
|
|
125
|
-
variants={variants}
|
|
126
|
-
initial="initial"
|
|
127
|
-
animate="animate"
|
|
128
|
-
exit="exit"
|
|
129
|
-
transition={{ duration: 0.2, ease: "easeInOut" }}
|
|
130
|
-
>
|
|
131
|
-
{renderPage()}
|
|
132
|
-
</motion.div>
|
|
133
|
-
</AnimatePresence>
|
|
134
|
-
</div>
|
|
135
|
-
</motion.div>
|
|
136
|
-
</div>
|
|
137
|
-
);
|
|
138
|
-
};
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
|
-
const About: React.FC = () => {
|
|
4
|
-
return (
|
|
5
|
-
<div className="cc-page-about">
|
|
6
|
-
<div className="cc-about-steps">
|
|
7
|
-
<div className="cc-about-step">
|
|
8
|
-
<div className="cc-step-num">1</div>
|
|
9
|
-
<div className="cc-step-content">
|
|
10
|
-
<h4>Get a Wallet</h4>
|
|
11
|
-
<p>A wallet lets you connect to Terra Classic and manage your LUNC assets safely.</p>
|
|
12
|
-
</div>
|
|
13
|
-
</div>
|
|
14
|
-
<div className="cc-about-step">
|
|
15
|
-
<div className="cc-step-num">2</div>
|
|
16
|
-
<div className="cc-step-content">
|
|
17
|
-
<h4>Add some LUNC</h4>
|
|
18
|
-
<p>You'll need some LUNC in your wallet to pay for gas fees on the Terra network.</p>
|
|
19
|
-
</div>
|
|
20
|
-
</div>
|
|
21
|
-
<div className="cc-about-step">
|
|
22
|
-
<div className="cc-step-num">3</div>
|
|
23
|
-
<div className="cc-step-content">
|
|
24
|
-
<h4>Connect & Stake</h4>
|
|
25
|
-
<p>Connect your wallet to this app to start staking, voting, or trading.</p>
|
|
26
|
-
</div>
|
|
27
|
-
</div>
|
|
28
|
-
</div>
|
|
29
|
-
|
|
30
|
-
<button className="cc-primary-btn" onClick={() => window.open('https://www.galaxy-station.app/', '_blank')}>
|
|
31
|
-
Get Galaxy Station
|
|
32
|
-
</button>
|
|
33
|
-
</div>
|
|
34
|
-
);
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export default About;
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
|
-
interface ConnectingProps {
|
|
4
|
-
wallet: any;
|
|
5
|
-
onCancel: () => void;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
const Connecting: React.FC<ConnectingProps> = ({ wallet, onCancel }) => {
|
|
9
|
-
return (
|
|
10
|
-
<div className="cc-page-connecting">
|
|
11
|
-
<div className="cc-connecting-view">
|
|
12
|
-
<div className="cc-spinner-container">
|
|
13
|
-
<div className="cc-spinner"></div>
|
|
14
|
-
{wallet?.icon && (
|
|
15
|
-
<img src={wallet.icon} alt="" className="cc-spinner-icon" />
|
|
16
|
-
)}
|
|
17
|
-
</div>
|
|
18
|
-
<h3 className="cc-connecting-title">Requesting Connection</h3>
|
|
19
|
-
<p className="cc-connecting-text">
|
|
20
|
-
Open the {wallet?.name || 'Wallet'} extension to continue.
|
|
21
|
-
</p>
|
|
22
|
-
<button className="cc-footer-btn" onClick={onCancel}>
|
|
23
|
-
Cancel
|
|
24
|
-
</button>
|
|
25
|
-
</div>
|
|
26
|
-
</div>
|
|
27
|
-
);
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export default Connecting;
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { useCosmos } from '../../CosmosProvider.js';
|
|
3
|
-
|
|
4
|
-
interface ConnectorsProps {
|
|
5
|
-
onSelect: (wallet: any) => void;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
const Connectors: React.FC<ConnectorsProps> = ({ onSelect }) => {
|
|
9
|
-
const { client } = useCosmos();
|
|
10
|
-
const wallets = client.getWallets();
|
|
11
|
-
|
|
12
|
-
return (
|
|
13
|
-
<div className="cc-page-connectors">
|
|
14
|
-
<div className="cc-wallet-list">
|
|
15
|
-
{wallets.map((wallet) => (
|
|
16
|
-
<button
|
|
17
|
-
key={wallet.id}
|
|
18
|
-
className="cc-wallet-item"
|
|
19
|
-
onClick={() => onSelect(wallet)}
|
|
20
|
-
>
|
|
21
|
-
<span>{wallet.name}</span>
|
|
22
|
-
{wallet.icon && <img src={wallet.icon} alt={wallet.name} className="cc-wallet-icon" />}
|
|
23
|
-
</button>
|
|
24
|
-
))}
|
|
25
|
-
</div>
|
|
26
|
-
</div>
|
|
27
|
-
);
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export default Connectors;
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import React, { useState } from 'react';
|
|
2
|
-
import { useCosmos } from '../../CosmosProvider.js';
|
|
3
|
-
import { useAccount, useDisconnect, useBalance } from '../../hooks.js';
|
|
4
|
-
import { Avatar } from '../Avatar.js';
|
|
5
|
-
|
|
6
|
-
const Profile: React.FC = () => {
|
|
7
|
-
const { client } = useCosmos();
|
|
8
|
-
const { address } = useAccount();
|
|
9
|
-
const { disconnect } = useDisconnect();
|
|
10
|
-
const { balance, isLoading: isBalanceLoading } = useBalance();
|
|
11
|
-
const [copyFeedback, setCopyFeedback] = useState(false);
|
|
12
|
-
|
|
13
|
-
const formatBalance = (bal: { amount: string; denom: string } | null) => {
|
|
14
|
-
if (!bal) return '0.00 LUNC';
|
|
15
|
-
const amount = parseFloat(bal.amount) / 1000000;
|
|
16
|
-
return `${amount.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} LUNC`;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const handleCopy = () => {
|
|
20
|
-
if (address) {
|
|
21
|
-
navigator.clipboard.writeText(address);
|
|
22
|
-
setCopyFeedback(true);
|
|
23
|
-
setTimeout(() => setCopyFeedback(false), 2000);
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
if (!address) return null;
|
|
28
|
-
|
|
29
|
-
return (
|
|
30
|
-
<div className="cc-page-profile">
|
|
31
|
-
<div className="cc-profile-view">
|
|
32
|
-
<div className="cc-profile-avatar">
|
|
33
|
-
<Avatar address={address} size={84} />
|
|
34
|
-
</div>
|
|
35
|
-
|
|
36
|
-
<div className="cc-profile-info">
|
|
37
|
-
<h3 className="cc-profile-address">
|
|
38
|
-
{address.slice(0, 12)}...{address.slice(-6)}
|
|
39
|
-
</h3>
|
|
40
|
-
<div className="cc-profile-balance">
|
|
41
|
-
{isBalanceLoading ? 'Loading...' : formatBalance(balance)}
|
|
42
|
-
</div>
|
|
43
|
-
</div>
|
|
44
|
-
|
|
45
|
-
<div className="cc-profile-actions">
|
|
46
|
-
<button className="cc-util-btn" onClick={handleCopy}>
|
|
47
|
-
{copyFeedback ? 'Copied!' : 'Copy Address'}
|
|
48
|
-
</button>
|
|
49
|
-
<button
|
|
50
|
-
className="cc-util-btn"
|
|
51
|
-
onClick={() => disconnect()}
|
|
52
|
-
style={{ color: '#ef4444' }}
|
|
53
|
-
>
|
|
54
|
-
Disconnect
|
|
55
|
-
</button>
|
|
56
|
-
</div>
|
|
57
|
-
|
|
58
|
-
<div className="cc-profile-footer">
|
|
59
|
-
Connected to {client.getChains()[0]?.chainId}
|
|
60
|
-
</div>
|
|
61
|
-
</div>
|
|
62
|
-
</div>
|
|
63
|
-
);
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
export default Profile;
|
package/src/hooks.ts
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { useState, useEffect } from 'react';
|
|
2
|
-
import { useCosmos } from './CosmosProvider.js';
|
|
3
|
-
import { useCallback } from 'react';
|
|
4
|
-
|
|
5
|
-
export const useAccount = () => {
|
|
6
|
-
const { state } = useCosmos();
|
|
7
|
-
return {
|
|
8
|
-
address: state.account?.address,
|
|
9
|
-
status: state.status,
|
|
10
|
-
isConnected: state.status === 'connected',
|
|
11
|
-
isConnecting: state.status === 'connecting',
|
|
12
|
-
isDisconnected: state.status === 'disconnected',
|
|
13
|
-
account: state.account,
|
|
14
|
-
};
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export const useConnect = () => {
|
|
18
|
-
const { client } = useCosmos();
|
|
19
|
-
|
|
20
|
-
const connect = useCallback(async (walletId: string, chainId: string) => {
|
|
21
|
-
return client.connect(walletId, chainId);
|
|
22
|
-
}, [client]);
|
|
23
|
-
|
|
24
|
-
return { connect };
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
export const useDisconnect = () => {
|
|
28
|
-
const { client } = useCosmos();
|
|
29
|
-
|
|
30
|
-
const disconnect = useCallback(async () => {
|
|
31
|
-
return client.disconnect();
|
|
32
|
-
}, [client]);
|
|
33
|
-
|
|
34
|
-
return { disconnect };
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export const useClient = () => {
|
|
38
|
-
const { client } = useCosmos();
|
|
39
|
-
return client;
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
export const useBalance = () => {
|
|
43
|
-
const { state } = useCosmos();
|
|
44
|
-
const [balance, setBalance] = useState<{ amount: string; denom: string } | null>(null);
|
|
45
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
46
|
-
|
|
47
|
-
useEffect(() => {
|
|
48
|
-
const address = state.account?.address;
|
|
49
|
-
const rest = state.currentChain?.rest;
|
|
50
|
-
|
|
51
|
-
if (address && rest) {
|
|
52
|
-
setIsLoading(true);
|
|
53
|
-
const fetchBalance = async () => {
|
|
54
|
-
try {
|
|
55
|
-
const res = await fetch(
|
|
56
|
-
`${rest}/cosmos/bank/v1beta1/balances/${address}/by_denom?denom=uluna`
|
|
57
|
-
);
|
|
58
|
-
const data = await res.json();
|
|
59
|
-
setBalance(data.balance || { amount: '0', denom: 'uluna' });
|
|
60
|
-
} catch (error) {
|
|
61
|
-
console.error('Failed to fetch balance:', error);
|
|
62
|
-
} finally {
|
|
63
|
-
setIsLoading(false);
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
fetchBalance();
|
|
67
|
-
} else {
|
|
68
|
-
setBalance(null);
|
|
69
|
-
}
|
|
70
|
-
}, [state.account?.address, state.currentChain]);
|
|
71
|
-
|
|
72
|
-
return { balance, isLoading };
|
|
73
|
-
};
|
package/src/index.ts
DELETED
package/tsconfig.json
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ESNext",
|
|
4
|
-
"module": "NodeNext",
|
|
5
|
-
"moduleResolution": "NodeNext",
|
|
6
|
-
"declaration": true,
|
|
7
|
-
"outDir": "./dist",
|
|
8
|
-
"strict": true,
|
|
9
|
-
"esModuleInterop": true,
|
|
10
|
-
"skipLibCheck": true,
|
|
11
|
-
"forceConsistentCasingInFileNames": true,
|
|
12
|
-
"jsx": "react-jsx",
|
|
13
|
-
"lib": ["dom", "dom.iterable", "esnext"]
|
|
14
|
-
},
|
|
15
|
-
"include": ["src/**/*"]
|
|
16
|
-
}
|
/package/{src → dist}/styles.css
RENAMED
|
File without changes
|