Skip to content

Commit 4c2f143

Browse files
authored
Merge pull request #29 from Silk-Nodes/claude/unruffled-ride
Add Cosmostation wallet support
2 parents 1ec8afb + ffe8419 commit 4c2f143

5 files changed

Lines changed: 50 additions & 16 deletions

File tree

public/cosmostation-logo.png

2.02 KB
Loading

src/app/page.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,31 @@ export default function HomePage() {
380380
</a>
381381
)}
382382
</button>
383+
<button
384+
onClick={() => { setShowWalletModal(false); connect("cosmostation"); trackEvent("wallet_connect", { wallet_type: "cosmostation" }); }}
385+
disabled={walletLoading}
386+
style={{
387+
display: "flex", alignItems: "center", gap: 14, padding: "14px 18px",
388+
borderRadius: "var(--radius-md)", border: "1px solid var(--glass-border)",
389+
background: "var(--glass-bg)", cursor: "pointer", width: "100%",
390+
opacity: availableWallets.cosmostation ? 1 : 0.4, transition: "all 0.15s",
391+
}}
392+
>
393+
<img src={`${BASE_PATH}/cosmostation-logo.png`} alt="Cosmostation wallet logo" style={{ width: 40, height: 40, borderRadius: 10 }} />
394+
<div style={{ textAlign: "left" }}>
395+
<div style={{ fontWeight: 600, fontSize: "0.9rem" }}>Cosmostation</div>
396+
<div style={{ fontSize: "0.7rem", color: "var(--text-light)" }}>
397+
{availableWallets.cosmostation ? "Detected" : "Not installed"}
398+
</div>
399+
</div>
400+
{!availableWallets.cosmostation && (
401+
<a href="https://www.cosmostation.io/products/cosmostation_extension" target="_blank" rel="noopener noreferrer"
402+
onClick={(e) => e.stopPropagation()}
403+
style={{ marginLeft: "auto", fontSize: "0.7rem", color: "var(--accent-olive)", textDecoration: "none", fontWeight: 600 }}>
404+
Install
405+
</a>
406+
)}
407+
</button>
383408
</div>
384409
<button
385410
onClick={() => setShowWalletModal(false)}

src/hooks/useWallet.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export function useWallet() {
4848
}
4949
}, [txResult]);
5050

51-
const connect = useCallback(async (walletType: "keplr" | "leap" = "keplr") => {
51+
const connect = useCallback(async (walletType: "keplr" | "leap" | "cosmostation" = "keplr") => {
5252
setLoading(true);
5353
setError(null);
5454
try {
@@ -152,10 +152,10 @@ export function useWallet() {
152152

153153
try {
154154
const wasConnected = localStorage.getItem("tx-wallet-connected");
155-
const savedType = localStorage.getItem("tx-wallet-type") as "keplr" | "leap" | null;
155+
const savedType = localStorage.getItem("tx-wallet-type") as "keplr" | "leap" | "cosmostation" | null;
156156
if (wasConnected === "true" && savedType) {
157157
const wallets = getAvailableWallets();
158-
if ((savedType === "keplr" && wallets.keplr) || (savedType === "leap" && wallets.leap)) {
158+
if ((savedType === "keplr" && wallets.keplr) || (savedType === "leap" && wallets.leap) || (savedType === "cosmostation" && wallets.cosmostation)) {
159159
connect(savedType);
160160
}
161161
}
@@ -173,12 +173,13 @@ export function useWallet() {
173173
};
174174

175175
window.addEventListener("keplr_keystorechange", handleAccountChange);
176-
// Leap uses the same event name
177176
window.addEventListener("leap_keystorechange", handleAccountChange);
177+
window.addEventListener("cosmostation_keystorechange", handleAccountChange);
178178

179179
return () => {
180180
window.removeEventListener("keplr_keystorechange", handleAccountChange);
181181
window.removeEventListener("leap_keystorechange", handleAccountChange);
182+
window.removeEventListener("cosmostation_keystorechange", handleAccountChange);
182183
};
183184
}, [wallet.connected, wallet.walletType, connect]);
184185

@@ -197,6 +198,6 @@ export function useWallet() {
197198
undelegate,
198199
clearError: () => setError(null),
199200
clearTxResult: () => setTxResult(null),
200-
availableWallets: typeof window !== "undefined" ? getAvailableWallets() : { keplr: false, leap: false },
201+
availableWallets: typeof window !== "undefined" ? getAvailableWallets() : { keplr: false, leap: false, cosmostation: false },
201202
};
202203
}

src/lib/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export interface WalletState {
7878
rewards: number;
7979
delegations: Delegation[];
8080
unbondingDelegations: UnbondingDelegation[];
81-
walletType: "keplr" | "leap" | "";
81+
walletType: "keplr" | "leap" | "cosmostation" | "";
8282
}
8383

8484
export interface Delegation {

src/lib/wallet.ts

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,32 +59,40 @@ function resolveMoniker(valAddr: string): string {
5959
}
6060

6161
// ── Detect available wallets ──
62-
export function getAvailableWallets(): { keplr: boolean; leap: boolean } {
63-
if (typeof window === "undefined") return { keplr: false, leap: false };
62+
export function getAvailableWallets(): { keplr: boolean; leap: boolean; cosmostation: boolean } {
63+
if (typeof window === "undefined") return { keplr: false, leap: false, cosmostation: false };
6464
return {
6565
keplr: !!(window as any).keplr,
6666
leap: !!(window as any).leap,
67+
cosmostation: !!(window as any).cosmostation,
6768
};
6869
}
6970

70-
// ── Get wallet provider (Keplr or Leap) ──
71-
function getWalletProvider(type: "keplr" | "leap") {
71+
// ── Get wallet provider (Keplr, Leap, or Cosmostation) ──
72+
function getWalletProvider(type: "keplr" | "leap" | "cosmostation") {
7273
if (typeof window === "undefined") return null;
7374
if (type === "leap") return (window as any).leap;
75+
if (type === "cosmostation") {
76+
// Cosmostation exposes a Keplr-compatible provider
77+
const cosmostation = (window as any).cosmostation;
78+
if (cosmostation?.providers?.keplr) return cosmostation.providers.keplr;
79+
// Fallback: some versions expose it directly
80+
return cosmostation;
81+
}
7482
return (window as any).keplr;
7583
}
7684

7785
/**
7886
* Connect wallet (Keplr or Leap) and return wallet state
7987
*/
80-
export async function connectWallet(walletType: "keplr" | "leap" = "keplr"): Promise<WalletState> {
88+
export async function connectWallet(walletType: "keplr" | "leap" | "cosmostation" = "keplr"): Promise<WalletState> {
8189
if (typeof window === "undefined") {
8290
throw new Error("Window not available");
8391
}
8492

8593
const provider = getWalletProvider(walletType);
8694
if (!provider) {
87-
const name = walletType === "leap" ? "Leap" : "Keplr";
95+
const name = walletType === "cosmostation" ? "Cosmostation" : walletType === "leap" ? "Leap" : "Keplr";
8896
throw new Error(
8997
`${name} wallet not found. Please install the ${name} browser extension.`
9098
);
@@ -240,7 +248,7 @@ async function fetchUnbondingDelegations(address: string): Promise<UnbondingDele
240248
export async function delegateTokens(
241249
validatorAddress: string,
242250
amount: number,
243-
walletType: "keplr" | "leap" = "keplr"
251+
walletType: "keplr" | "leap" | "cosmostation" = "keplr"
244252
): Promise<string> {
245253
const provider = getWalletProvider(walletType);
246254
if (!provider) throw new Error(`${walletType} not available`);
@@ -278,7 +286,7 @@ export async function delegateTokens(
278286
export async function undelegateTokens(
279287
validatorAddress: string,
280288
amount: number,
281-
walletType: "keplr" | "leap" = "keplr"
289+
walletType: "keplr" | "leap" | "cosmostation" = "keplr"
282290
): Promise<string> {
283291
const provider = getWalletProvider(walletType);
284292
if (!provider) throw new Error(`${walletType} not available`);
@@ -320,7 +328,7 @@ export async function undelegateTokens(
320328
*/
321329
export async function claimAllRewards(
322330
delegations: Delegation[],
323-
walletType: "keplr" | "leap" = "keplr"
331+
walletType: "keplr" | "leap" | "cosmostation" = "keplr"
324332
): Promise<string> {
325333
const provider = getWalletProvider(walletType);
326334
if (!provider) throw new Error(`${walletType} not available`);
@@ -377,7 +385,7 @@ export async function redelegateTokens(
377385
srcValidatorAddress: string,
378386
dstValidatorAddress: string,
379387
amount: number,
380-
walletType: "keplr" | "leap" = "keplr"
388+
walletType: "keplr" | "leap" | "cosmostation" = "keplr"
381389
): Promise<string> {
382390
const provider = getWalletProvider(walletType);
383391
if (!provider) throw new Error(`${walletType} not available`);

0 commit comments

Comments
 (0)