Skip to content

Commit b0074d3

Browse files
add use case for specify wallet usage
1 parent 3538e09 commit b0074d3

File tree

6 files changed

+276
-14
lines changed

6 files changed

+276
-14
lines changed

docs/usage.mdx

Lines changed: 170 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,4 +414,173 @@ For advanced configuration options, you can provide additional options to the Ch
414414

415415
- [InterchainJS Documentation](https://docs.hyperweb.io/interchainjs)
416416
- [Chain Registry Documentation](https://github.com/hyperweb-io/chain-registry)
417-
- [Example Applications](https://github.com/hyperweb-io/interchain-kit/tree/main/examples)
417+
- [Example Applications](https://github.com/hyperweb-io/interchain-kit/tree/main/examples)
418+
419+
## Signing Arbitrary Messages with Cosmos Wallet
420+
421+
Interchain Kit allows you to sign arbitrary messages using a Cosmos Wallet:
422+
423+
```tsx
424+
import {
425+
CosmosWallet,
426+
ExtensionWallet,
427+
isInstanceOf,
428+
MultiChainWallet,
429+
} from "@interchain-kit/core";
430+
import { useChain } from "@interchain-kit/react";
431+
import { useState } from "react";
432+
433+
const CosmosWalletExample: React.FC = () => {
434+
// Connect to a specific chain
435+
const { wallet, connect, address, disconnect, chain } =
436+
useChain("osmosistestnet");
437+
438+
const [message, setMessage] = useState("");
439+
const [signature, setSignature] = useState("");
440+
441+
const handleConnect = async () => {
442+
connect();
443+
};
444+
445+
const handleDisconnect = async () => {
446+
disconnect();
447+
};
448+
449+
const handleSignArbitrary = async () => {
450+
451+
// get specific wallet to use its own methods
452+
453+
const cosmosWallet = wallet.getWalletOfType(CosmosWallet);
454+
455+
if (cosmosWallet) {
456+
const signed = await cosmosWallet.signArbitrary(
457+
chain.chainId as string,
458+
address,
459+
message
460+
);
461+
462+
setSignature(signed.signature);
463+
}
464+
};
465+
466+
return (
467+
<div>
468+
<h1>Cosmos Wallet</h1>
469+
{address ? (
470+
<div>
471+
<p>Connected Address: {address}</p>
472+
<button onClick={handleDisconnect}>Disconnect</button>
473+
</div>
474+
) : (
475+
<button onClick={handleConnect}>Connect Wallet</button>
476+
)}
477+
478+
<div>
479+
<h2>Sign Arbitrary Message</h2>
480+
<textarea
481+
rows={4}
482+
cols={50}
483+
placeholder="Enter a message to sign"
484+
value={message}
485+
onChange={(e) => setMessage(e.target.value)}
486+
/>
487+
<br />
488+
<button onClick={handleSignArbitrary}>
489+
Sign Message
490+
</button>
491+
{signature && (
492+
<div>
493+
<h3>Signature:</h3>
494+
<pre>{signature}</pre>
495+
</div>
496+
)}
497+
</div>
498+
</div>
499+
);
500+
};
501+
```
502+
503+
This example demonstrates how to:
504+
1. Connect to a specific chain using `useChain`
505+
2. Get a Cosmos wallet instance using `wallet.getWalletOfType(CosmosWallet)`
506+
3. Sign arbitrary messages with `cosmosWallet.signArbitrary()`
507+
4. Display the resulting signature to the user
508+
509+
## Signing Messages with Ethereum Wallet
510+
511+
Interchain Kit also allows you to sign messages using an Ethereum Wallet:
512+
513+
```tsx
514+
import { EthereumWallet } from "@interchain-kit/core";
515+
import { useChain } from "@interchain-kit/react";
516+
import React, { useState } from "react";
517+
518+
const EthereumWalletExample: React.FC = () => {
519+
const [message, setMessage] = useState<string>("");
520+
const [signature, setSignature] = useState<string | null>(null);
521+
522+
// Connect to Ethereum chain
523+
const { connect, address, disconnect, wallet } = useChain("ethereum");
524+
525+
const connectWallet = async () => {
526+
connect();
527+
};
528+
529+
const disconnectWallet = async () => {
530+
disconnect();
531+
setSignature(null);
532+
};
533+
534+
const signMessage = async () => {
535+
536+
// get specific wallet to use its own methods
537+
538+
const ethereumWallet = wallet.getWalletOfType(EthereumWallet);
539+
if (ethereumWallet) {
540+
try {
541+
const signedMessage = await ethereumWallet.signMessage(message);
542+
setSignature(signedMessage);
543+
} catch (error) {
544+
console.error("Error signing message:", error);
545+
}
546+
}
547+
};
548+
549+
return (
550+
<div>
551+
<h2>Ethereum Sign Message Example</h2>
552+
{!address ? (
553+
<button onClick={connectWallet}>Connect Wallet</button>
554+
) : (
555+
<button onClick={disconnectWallet}>Disconnect Wallet</button>
556+
)}
557+
<div>
558+
<div>
559+
<strong>Connected:</strong> {address}
560+
</div>
561+
<textarea
562+
rows={3}
563+
style={{ width: "100%", marginTop: 16 }}
564+
value={message}
565+
onChange={(e) => setMessage(e.target.value)}
566+
/>
567+
<button style={{ marginTop: 16 }} onClick={signMessage}>
568+
Sign Message
569+
</button>
570+
</div>
571+
{signature && (
572+
<div style={{ marginTop: 16 }}>
573+
<strong>Signature:</strong>
574+
<pre>{signature}</pre>
575+
</div>
576+
)}
577+
</div>
578+
);
579+
};
580+
```
581+
582+
This example demonstrates how to:
583+
1. Connect to the Ethereum chain using `useChain("ethereum")`
584+
2. Get an Ethereum wallet instance using `wallet.getWalletOfType(EthereumWallet)`
585+
3. Sign messages with `ethereumWallet.signMessage()`
586+
4. Display the resulting signature to the user

examples/react/src/App.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import LedgerExample from "./pages/leger";
88
import Mobile from "./pages/mobile";
99
import CosmosWalletPage from "./pages/cosmos-wallet";
1010
import TestDisconnect from "./pages/test-disconnect";
11+
import EthereumSignMessage from "./pages/ethereum-wallet";
1112

1213
function Layout() {
1314
return <Outlet />;
@@ -26,6 +27,7 @@ export default function App() {
2627
<Route path="mobile" element={<Mobile />} />
2728
<Route path="cosmos-wallet" element={<CosmosWalletPage />} />
2829
<Route path="test-disconnect" element={<TestDisconnect />} />
30+
<Route path="ethereum-wallet" element={<EthereumSignMessage />} />
2931
</Route>
3032
</Routes>
3133
);

examples/react/src/main.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,14 @@ import { create } from "domain";
4949

5050
const chainNames: string[] = [
5151
// "injectivetestnet",
52-
"osmosistestnet",
52+
// "osmosistestnet",
5353
// "osmosis",
5454
// "juno",
5555
// "cosmoshub",
5656
// "stargaze",
5757
// "noble",
5858
// "seitestnet2",
59-
// "ethereum",
59+
"ethereum",
6060
// "cosmoshubtestnet",
6161
];
6262
// const chainNames = ["osmosistestnet"];

examples/react/src/pages/cosmos-wallet.tsx

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
1-
import {
2-
CosmosWallet,
3-
ExtensionWallet,
4-
isInstanceOf,
5-
MultiChainWallet,
6-
} from "@interchain-kit/core";
1+
import { CosmosWallet } from "@interchain-kit/core";
72
import { useChain } from "@interchain-kit/react";
83
import { useState } from "react";
94

105
const CosmosWalletPage: React.FC = () => {
11-
const { wallet, connect, address, disconnect, chain } = useChain("osmosis");
6+
const { wallet, connect, address, disconnect, chain } =
7+
useChain("osmosistestnet");
128

139
const [message, setMessage] = useState("");
1410
const [signature, setSignature] = useState("");
@@ -22,11 +18,9 @@ const CosmosWalletPage: React.FC = () => {
2218
};
2319

2420
const handleSignArbitrary = async () => {
25-
if (wallet instanceof MultiChainWallet) {
26-
const cosmosWallet = (await wallet.getWalletByChainType(
27-
"cosmos"
28-
)) as CosmosWallet;
21+
const cosmosWallet = wallet.getWalletOfType(CosmosWallet);
2922

23+
if (cosmosWallet) {
3024
const signed = await cosmosWallet.signArbitrary(
3125
chain.chainId as string,
3226
address,
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { EthereumWallet } from "@interchain-kit/core";
2+
import { useChain } from "@interchain-kit/react";
3+
import React, { useState } from "react";
4+
5+
const EthereumSignMessage: React.FC = () => {
6+
const [message, setMessage] = useState<string>("");
7+
const [signature, setSignature] = useState<string | null>(null);
8+
9+
const { connect, address, disconnect, wallet } = useChain("ethereum");
10+
11+
const connectWallet = async () => {
12+
connect();
13+
};
14+
15+
const disconnectWallet = async () => {
16+
disconnect();
17+
setSignature(null);
18+
};
19+
20+
const signMessage = async () => {
21+
const ethereumWallet = wallet.getWalletOfType(EthereumWallet);
22+
if (ethereumWallet) {
23+
try {
24+
const signedMessage = await ethereumWallet.signMessage(message);
25+
setSignature(signedMessage);
26+
} catch (error) {
27+
console.error("Error signing message:", error);
28+
}
29+
}
30+
};
31+
32+
return (
33+
<div
34+
style={{ maxWidth: 500, margin: "2rem auto", fontFamily: "sans-serif" }}
35+
>
36+
<h2>Ethereum Sign Message Example</h2>
37+
{!address ? (
38+
<button onClick={connectWallet}>Connect Wallet</button>
39+
) : (
40+
<button onClick={disconnectWallet}>Disconnect Wallet</button>
41+
)}
42+
<div>
43+
<div>
44+
<strong>Connected:</strong> {address}
45+
</div>
46+
<textarea
47+
rows={3}
48+
style={{ width: "100%", marginTop: 16 }}
49+
value={message}
50+
onChange={(e) => setMessage(e.target.value)}
51+
/>
52+
<button style={{ marginTop: 16 }} onClick={signMessage}>
53+
Sign Message
54+
</button>
55+
</div>
56+
{signature && (
57+
<div style={{ marginTop: 16 }}>
58+
<strong>Signature:</strong>
59+
<pre style={{ whiteSpace: "break-spaces" }}>{signature}</pre>
60+
</div>
61+
)}
62+
</div>
63+
);
64+
};
65+
66+
export default EthereumSignMessage;

packages/core/src/wallets/ethereum-wallet.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { BaseWallet } from "./base-wallet";
44
import { delay, getClientFromExtension } from "../utils";
55
import { EthereumNetwork } from "../types/ethereum";
66
import { IGenericOfflineSigner } from '@interchainjs/types';
7+
import { fromByteArray, toByteArray } from "base64-js";
78

89
export class EthereumWallet extends BaseWallet {
910

@@ -38,6 +39,7 @@ export class EthereumWallet extends BaseWallet {
3839
async disconnect(chainId: Chain["chainId"]): Promise<void> {
3940
// throw new Error("Method not implemented.");
4041
console.log('eth disconnect')
42+
return new Promise((resolve, reject) => { resolve() })
4143
}
4244
async switchChain(chainId: string): Promise<void> {
4345
if (!chainId.startsWith("0x")) {
@@ -125,4 +127,33 @@ export class EthereumWallet extends BaseWallet {
125127
console.log('transactionHash:', txHash);
126128
return txHash;
127129
}
130+
131+
async signMessage(message: string) {
132+
if (!this.ethereum) {
133+
throw new Error("MetaMask is not installed");
134+
}
135+
136+
try {
137+
// Request account access
138+
const accounts = await this.ethereum.request({
139+
method: "eth_requestAccounts",
140+
});
141+
const account = accounts[0];
142+
143+
// Encode message to Base64
144+
const hexMessage = fromByteArray(new TextEncoder().encode(message));
145+
146+
// Sign the message
147+
const signature = await this.ethereum.request({
148+
method: "personal_sign",
149+
params: [hexMessage, account],
150+
});
151+
152+
console.log("Signature:", signature);
153+
return signature;
154+
} catch (error) {
155+
console.error("Error signing message:", error);
156+
throw error;
157+
}
158+
}
128159
}

0 commit comments

Comments
 (0)