Skip to content

Commit 24aedf8

Browse files
committed
feat: sui + personal sign
1 parent 1d0405d commit 24aedf8

29 files changed

+1213
-537
lines changed

advanced/dapps/react-dapp-v2/package.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"@walletconnect/utils": "2.20.1",
3232
"@reown/appkit": "1.7.5",
3333
"axios": "^1.0.0",
34+
"@mysten/sui": "^1.29.1",
3435
"bitcoinjs-lib": "^6.1.5",
3536
"bitcoinjs-message": "^2.2.0",
3637
"blockies-ts": "^1.0.0",
@@ -104,7 +105,15 @@
104105
"semver@>=7.0.0 <7.5.2": ">=7.5.2",
105106
"next@>=9.5.5 <14.2.15": ">=14.2.15",
106107
"ansi-html@<0.0.8": ">=0.0.8",
107-
"axios@<1.8.2": ">=1.8.2"
108+
"axios@<1.8.2": ">=1.8.2",
109+
"@walletconnect/core@": ">=2.20.2",
110+
"@walletconnect/encoding@": ">=1.0.1",
111+
"@walletconnect/jsonrpc-utils@": ">=1.0.8",
112+
"@walletconnect/types@": ">=2.20.2",
113+
"@walletconnect/universal-provider@": ">=2.20.2",
114+
"@walletconnect/sign-client@": ">=2.20.2",
115+
"@walletconnect/utils@": ">=2.20.2",
116+
"@walletconnect/ethereum-provider@": ">=2.20.2"
108117
}
109118
}
110119
}

advanced/dapps/react-dapp-v2/pnpm-lock.yaml

Lines changed: 163 additions & 515 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Loading

advanced/dapps/react-dapp-v2/src/chains/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import * as tron from "./tron";
1010
import * as tezos from "./tezos";
1111
import * as kadena from "./kadena";
1212
import * as bip122 from "./bip122";
13+
import * as sui from "./sui";
1314

1415
import { ChainMetadata, ChainRequestRender } from "../helpers";
1516

@@ -36,6 +37,8 @@ export function getChainMetadata(chainId: string): ChainMetadata {
3637
return tezos.getChainMetadata(chainId);
3738
case "bip122":
3839
return bip122.getChainMetadata(chainId);
40+
case "sui":
41+
return sui.getChainMetadata(chainId);
3942
default:
4043
throw new Error(`No metadata handler for namespace ${namespace}`);
4144
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { NamespaceMetadata, ChainMetadata, ChainsMap } from "../helpers";
2+
3+
export const SUI_MAINNET = "mainnet";
4+
export const SUI_TESTNET = "testnet";
5+
export const SUI_DEVNET = "devnet";
6+
7+
export const SuiChainData: ChainsMap = {
8+
[SUI_MAINNET]: {
9+
id: `sui:${SUI_MAINNET}`,
10+
name: "SUI Mainnet",
11+
rpc: [],
12+
slip44: 0,
13+
testnet: false,
14+
},
15+
[SUI_TESTNET]: {
16+
id: `sui:${SUI_TESTNET}`,
17+
name: "SUI Testnet",
18+
rpc: [],
19+
slip44: 0,
20+
testnet: true,
21+
},
22+
[SUI_DEVNET]: {
23+
id: `sui:${SUI_DEVNET}`,
24+
name: "SUI Devnet",
25+
rpc: [],
26+
slip44: 0,
27+
testnet: true,
28+
},
29+
};
30+
31+
export const SuiMetadata: NamespaceMetadata = {
32+
[SUI_MAINNET]: {
33+
logo: "/assets/sui.png",
34+
rgb: "6, 135, 245",
35+
},
36+
[SUI_TESTNET]: {
37+
logo: "/assets/sui.png",
38+
rgb: "6, 135, 245",
39+
},
40+
[SUI_DEVNET]: {
41+
logo: "/assets/sui.png",
42+
rgb: "6, 135, 245",
43+
},
44+
};
45+
46+
export function getChainMetadata(chainId: string): ChainMetadata {
47+
const reference = chainId.split(":")[1];
48+
const metadata = SuiMetadata[reference];
49+
if (typeof metadata === "undefined") {
50+
throw new Error(`No chain metadata found for chainId: ${chainId}`);
51+
}
52+
return metadata;
53+
}

advanced/dapps/react-dapp-v2/src/components/Button.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ const SButton = styled.button<ButtonStyleProps>`
109109
const Button = (props: ButtonProps) => (
110110
<SButton
111111
{...props}
112+
onClick={props.onClick}
112113
type={props.type}
113114
outline={props.outline}
114115
color={props.color}

advanced/dapps/react-dapp-v2/src/components/Column.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,16 @@ const Column = (props: ColumnProps) => {
3030
return (
3131
<SColumn
3232
{...props}
33-
spanHeight={spanHeight}
34-
maxWidth={maxWidth}
35-
center={center}
33+
style={{
34+
width: maxWidth ? `${maxWidth}px` : "100%",
35+
height: spanHeight ? "100%" : "auto",
36+
margin: "0 auto",
37+
display: "flex",
38+
flexDirection: "column",
39+
alignItems: center === undefined || center ? "center" : "flex-start",
40+
justifyContent:
41+
center === undefined || center ? "center" : "flex-start",
42+
}}
3643
>
3744
{children}
3845
</SColumn>

advanced/dapps/react-dapp-v2/src/constants/default.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export const DEFAULT_MAIN_CHAINS = [
2020
"tezos:mainnet",
2121
"kadena:mainnet01",
2222
"bip122:000000000019d6689c085ae165831e93",
23+
"sui:mainnet",
2324
];
2425

2526
export const DEFAULT_TEST_CHAINS = [
@@ -40,6 +41,8 @@ export const DEFAULT_TEST_CHAINS = [
4041
"tezos:testnet",
4142
"kadena:testnet04",
4243
"bip122:000000000933ea01ad0ee984209779ba",
44+
"sui:testnet",
45+
"sui:devnet",
4346
];
4447

4548
export const DEFAULT_CHAINS = [...DEFAULT_MAIN_CHAINS, ...DEFAULT_TEST_CHAINS];
@@ -287,6 +290,20 @@ export enum DEFAULT_BIP122_EVENTS {
287290
BIP122_ADDRESS_CHANGED = "bip122_addressesChanged",
288291
}
289292

293+
/**
294+
* SUI
295+
*/
296+
export enum DEFAULT_SUI_METHODS {
297+
SUI_SIGN_TRANSACTION = "sui_signTransaction",
298+
SUI_SIGN_AND_EXECUTE_TRANSACTION = "sui_signAndExecuteTransaction",
299+
SUI_SIGN_PERSONAL_MESSAGE = "sui_signPersonalMessage",
300+
}
301+
302+
export enum DEFAULT_SUI_EVENTS {
303+
SUI_ACCOUNTS_CHANGED = "sui_accountsChanged",
304+
SUI_CHAIN_CHANGED = "sui_chainChanged",
305+
}
306+
290307
export const REGIONALIZED_RELAYER_ENDPOINTS: RelayerType[] = [
291308
{
292309
value: DEFAULT_RELAY_URL,

advanced/dapps/react-dapp-v2/src/contexts/ChainDataContext.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { EIP155ChainData } from "../chains/eip155";
1717
import { TezosChainData } from "../chains/tezos";
1818
import { KadenaChainData } from "../chains/kadena";
1919
import { BtcChainData } from "../chains/bip122";
20+
import { SuiChainData } from "../chains/sui";
2021

2122
/**
2223
* Types
@@ -77,6 +78,9 @@ export function ChainDataContextProvider({
7778
case "bip122":
7879
chains = BtcChainData;
7980
break;
81+
case "sui":
82+
chains = SuiChainData;
83+
break;
8084
default:
8185
console.error("Unknown chain namespace: ", namespace);
8286
}

advanced/dapps/react-dapp-v2/src/contexts/JsonRpcContext.tsx

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import * as encoding from "@walletconnect/encoding";
44
import { Transaction as EthTransaction } from "@ethereumjs/tx";
55
import { recoverTransaction } from "@celo/wallet-base";
66
import * as bitcoin from "bitcoinjs-lib";
7+
import { verifyPersonalMessageSignature } from "@mysten/sui/verify";
78

89
import {
910
formatDirectSignDoc,
@@ -61,6 +62,7 @@ import {
6162
DEFAULT_EIP7715_METHODS,
6263
WalletGrantPermissionsParameters,
6364
WalletGrantPermissionsReturnType,
65+
DEFAULT_SUI_METHODS,
6466
} from "../constants";
6567
import { useChainData } from "./ChainDataContext";
6668
import { rpcProvidersByChainId } from "../../src/helpers/api";
@@ -156,6 +158,11 @@ interface IContext {
156158
testSendTransaction: TRpcRequestCallback;
157159
testSignPsbt: TRpcRequestCallback;
158160
};
161+
suiRpc: {
162+
testSendSuiTransaction: TRpcRequestCallback;
163+
testSignSuiTransaction: TRpcRequestCallback;
164+
testSignSuiPersonalMessage: TRpcRequestCallback;
165+
};
159166
rpcResult?: IFormattedRpcResponse | null;
160167
isRpcRequestPending: boolean;
161168
isTestnet: boolean;
@@ -1889,6 +1896,111 @@ export function JsonRpcContextProvider({
18891896
),
18901897
};
18911898

1899+
const suiRpc = {
1900+
testSendSuiTransaction: _createJsonRpcRequestHandler(
1901+
async (
1902+
chainId: string,
1903+
address: string
1904+
): Promise<IFormattedRpcResponse> => {
1905+
const method = DEFAULT_SUI_METHODS.SUI_SIGN_AND_EXECUTE_TRANSACTION;
1906+
const req = {
1907+
account: address,
1908+
recipientAddress: address,
1909+
amount: 1000000000000000000,
1910+
};
1911+
const result = await client!.request<{ txid: string }>({
1912+
topic: session!.topic,
1913+
chainId: chainId,
1914+
request: {
1915+
method,
1916+
params: req,
1917+
},
1918+
});
1919+
return {
1920+
method,
1921+
address: address,
1922+
valid: true,
1923+
result: result?.txid,
1924+
};
1925+
}
1926+
),
1927+
testSignSuiTransaction: _createJsonRpcRequestHandler(
1928+
async (
1929+
chainId: string,
1930+
address: string
1931+
): Promise<IFormattedRpcResponse> => {
1932+
const method = DEFAULT_SUI_METHODS.SUI_SIGN_TRANSACTION;
1933+
const req = {
1934+
account: address,
1935+
};
1936+
const result = await client!.request<{ txid: string }>({
1937+
topic: session!.topic,
1938+
chainId: chainId,
1939+
request: {
1940+
method,
1941+
params: req,
1942+
},
1943+
});
1944+
return {
1945+
method,
1946+
address: address,
1947+
valid: true,
1948+
result: result?.txid,
1949+
};
1950+
}
1951+
),
1952+
testSignSuiPersonalMessage: _createJsonRpcRequestHandler(
1953+
async (
1954+
chainId: string,
1955+
address: string
1956+
): Promise<IFormattedRpcResponse> => {
1957+
const method = DEFAULT_SUI_METHODS.SUI_SIGN_PERSONAL_MESSAGE;
1958+
const req = {
1959+
address: address,
1960+
message: Buffer.from(
1961+
"This is a message to be signed for SUI"
1962+
).toString("base64"),
1963+
};
1964+
const result = await client!.request<{
1965+
signature: string;
1966+
publicKey: string;
1967+
}>({
1968+
topic: session!.topic,
1969+
chainId: chainId,
1970+
request: {
1971+
method,
1972+
params: req,
1973+
},
1974+
});
1975+
1976+
console.log("result", result);
1977+
try {
1978+
const publicKey = await verifyPersonalMessageSignature(
1979+
new TextEncoder().encode(req.message),
1980+
Buffer.from(result.signature, "base64").toString(),
1981+
{ address }
1982+
);
1983+
console.log("publicKey", publicKey.toSuiAddress(), address);
1984+
return {
1985+
method,
1986+
address: address,
1987+
valid:
1988+
publicKey.toSuiAddress().toLowerCase() === address.toLowerCase(),
1989+
result: result?.signature,
1990+
};
1991+
} catch (error) {
1992+
console.error(error);
1993+
return {
1994+
method,
1995+
address: address,
1996+
valid: false,
1997+
result: (error as Error).message,
1998+
};
1999+
}
2000+
}
2001+
),
2002+
};
2003+
18922004
return (
18932005
<JsonRpcContext.Provider
18942006
value={{
@@ -1907,6 +2019,7 @@ export function JsonRpcContextProvider({
19072019
isTestnet,
19082020
setIsTestnet,
19092021
bip122Rpc,
2022+
suiRpc,
19102023
}}
19112024
>
19122025
{children}

advanced/dapps/react-dapp-v2/src/helpers/namespaces.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import {
2121
DEFAULT_OPTIONAL_METHODS,
2222
DEFAULT_BIP122_METHODS,
2323
DEFAULT_BIP122_EVENTS,
24+
DEFAULT_SUI_METHODS,
25+
DEFAULT_SUI_EVENTS,
2426
} from "../constants";
2527

2628
export const getNamespacesFromChains = (chains: string[]) => {
@@ -57,6 +59,8 @@ export const getSupportedRequiredMethodsByNamespace = (namespace: string) => {
5759
return Object.values(DEFAULT_KADENA_METHODS);
5860
case "bip122":
5961
return Object.values(DEFAULT_BIP122_METHODS);
62+
case "sui":
63+
return Object.values(DEFAULT_SUI_METHODS);
6064
default:
6165
throw new Error(
6266
`No default required methods for namespace: ${namespace}`
@@ -107,6 +111,8 @@ export const getSupportedEventsByNamespace = (namespace: string) => {
107111
return Object.values(DEFAULT_KADENA_EVENTS);
108112
case "bip122":
109113
return Object.values(DEFAULT_BIP122_EVENTS);
114+
case "sui":
115+
return Object.values(DEFAULT_SUI_EVENTS);
110116
default:
111117
throw new Error(`No default events for namespace: ${namespace}`);
112118
}

0 commit comments

Comments
 (0)