Skip to content

Commit

Permalink
feat: add swie
Browse files Browse the repository at this point in the history
  • Loading branch information
LCJove committed Oct 26, 2024
1 parent f5c82c5 commit 696de5b
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 59 deletions.
24 changes: 24 additions & 0 deletions packages/common/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { type CreateSiweMessageParameters } from 'viem/siwe';

export interface Account {
address: string;
name?: string;
Expand Down Expand Up @@ -119,6 +121,7 @@ export interface UniversalWeb3ProviderInterface {

// For Bitcoin, tokenId is undefined.
getNFTMetadata?: (params: { address: string; tokenId?: bigint }) => Promise<NFTMetadata>;
swie?: SWIEConfig;
}

export interface Wallet extends WalletMetadata {
Expand Down Expand Up @@ -327,3 +330,24 @@ export type Token = {
contract?: string;
}[];
};

export interface SignConfig {
// required
signIn: (options: { address: string; chainId: number }) => Promise<void>;
signOut: () => Promise<void>;

// WIP: optional
// signOutOnDisconnect?: boolean; // defaults true
// signOutOnAccountChange?: boolean; // defaults true
// signOutOnNetworkChange?: boolean; // defaults true
}

export interface SWIEConfig {
getNonce: (address: string, chainId?: number) => Promise<string>;
createMessage: (args: CreateSiweMessageParameters) => string;
verifyMessage: (message: string, signature: string) => Promise<boolean>;

// WIP: optional
// getSession?: () => Promise<SIWESession | null>;
// signOut?: () => Promise<boolean>;
}
1 change: 0 additions & 1 deletion packages/common/src/web3-config-provider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ const ProviderChildren: React.FC<
ConfigConsumerProps & { children?: React.ReactNode; parentContext?: ConfigConsumerProps }
> = (props) => {
const { children, parentContext, ...rest } = props;

const config = { ...parentContext };

Object.keys(rest).forEach((key) => {
Expand Down
4 changes: 4 additions & 0 deletions packages/wagmi/src/wagmi-provider/config-provider.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import {
SWIEConfig,
Web3ConfigProvider,
type Account,
type Chain,
Expand Down Expand Up @@ -34,6 +35,7 @@ export interface AntDesignWeb3ConfigProviderProps {
eip6963?: EIP6963Config;
wagimConfig: WagmiConfig;
useWalletConnectOfficialModal?: boolean;
swie?: SWIEConfig;
}

export const AntDesignWeb3ConfigProvider: React.FC<AntDesignWeb3ConfigProviderProps> = (props) => {
Expand All @@ -47,6 +49,7 @@ export const AntDesignWeb3ConfigProvider: React.FC<AntDesignWeb3ConfigProviderPr
eip6963,
wagimConfig,
useWalletConnectOfficialModal,
swie,
} = props;
const { address, isDisconnected, chain } = useAccount();
const config = useConfig();
Expand Down Expand Up @@ -192,6 +195,7 @@ export const AntDesignWeb3ConfigProvider: React.FC<AntDesignWeb3ConfigProviderPr
availableChains={chainList}
chain={currentChain}
account={account}
swie={swie}
balance={
balance
? {
Expand Down
10 changes: 6 additions & 4 deletions packages/wagmi/src/wagmi-provider/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import type { Locale } from '@ant-design/web3-common';
import type { Locale, SWIEConfig } from '@ant-design/web3-common';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import type { Transport, Chain as WagmiChain } from 'viem';
import { createConfig, http, WagmiProvider } from 'wagmi';
Expand Down Expand Up @@ -27,7 +27,7 @@ export interface WalletConnectOptions
useWalletConnectOfficialModal?: boolean;
}

export type WagmiWeb3ConfigProviderProps = {
export interface WagmiWeb3ConfigProviderProps {
config?: Config;
locale?: Locale;
wallets?: WalletFactory[];
Expand All @@ -40,7 +40,8 @@ export type WagmiWeb3ConfigProviderProps = {
reconnectOnMount?: boolean;
walletConnect?: false | WalletConnectOptions;
transports?: Record<number, Transport>;
};
swie?: SWIEConfig;
}

export function WagmiWeb3ConfigProvider({
children,
Expand All @@ -54,6 +55,7 @@ export function WagmiWeb3ConfigProvider({
eip6963,
walletConnect,
transports,
swie,
...restProps
}: React.PropsWithChildren<WagmiWeb3ConfigProviderProps>): React.ReactElement {
// When user custom config, add Mainnet by default
Expand All @@ -63,7 +65,6 @@ export function WagmiWeb3ConfigProvider({
: chains?.length
? chains
: [Mainnet];

const generateConfigFlag = () => {
return `${JSON.stringify(walletConnect)}-${chains.map((item) => item.id).join(',')}-${wallets.map((item) => item.name).join(',')}`;
};
Expand Down Expand Up @@ -138,6 +139,7 @@ export function WagmiWeb3ConfigProvider({
balance={balance}
eip6963={eip6963}
wagimConfig={wagmiConfig}
swie={swie}
useWalletConnectOfficialModal={
typeof walletConnect === 'object' && walletConnect?.useWalletConnectOfficialModal
}
Expand Down
8 changes: 7 additions & 1 deletion packages/web3/src/ethereum/demos/siwe/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { ConnectButton, Connector } from '@ant-design/web3';
import {
Mainnet,
MetaMask,
Expand All @@ -8,15 +7,22 @@ import {
WalletConnect,
} from '@ant-design/web3-wagmi';
import { QueryClient } from '@tanstack/react-query';
import { createSiweMessage } from 'viem/siwe';
import { http } from 'wagmi';

import { getNonce, verifyMessage } from './mock-api';
import SignBtn from './sign-btn';

const queryClient = new QueryClient();

const App: React.FC = () => {
return (
<WagmiWeb3ConfigProvider
swie={{
getNonce,
createMessage: (props) => createSiweMessage({ ...props, statement: 'Ant Design Web3' }),
verifyMessage: verifyMessage,
}}
eip6963={{
autoAddInjectedWallets: true,
}}
Expand Down
57 changes: 4 additions & 53 deletions packages/web3/src/ethereum/demos/siwe/sign-btn.tsx
Original file line number Diff line number Diff line change
@@ -1,60 +1,11 @@
import { useCallback, useState } from 'react';
import { Account, ConnectButton, Connector, useAccount } from '@ant-design/web3';
import { Mainnet } from '@ant-design/web3-wagmi';
import { Button, message, Space } from 'antd';
import { createSiweMessage } from 'viem/siwe';
import { useSignMessage } from 'wagmi';
import { ConnectButton, Connector, useAccount } from '@ant-design/web3';
import { Button, Space } from 'antd';

import { getNonce, verifyMessage } from './mock-api';
import { useSwie } from './useSwie';

export default function App() {
const { account } = useAccount();

const [signed, setSigned] = useState<boolean>(false);
const [signLoading, setSignLoading] = useState<boolean>(false);
const { signMessageAsync } = useSignMessage();

const signIn = useCallback(async (a?: Account) => {
const address = a?.address as `0x${string}`;

if (!address) {
message.error('Please connect wallet first.');
return;
}

// get nonce
const nonce = await getNonce(address);
if (!nonce) {
message.error('Failed to get nonce.');
return;
}

let msg: string;
let signature: `0x${string}`;

try {
msg = createSiweMessage({
domain: window.location.hostname,
address,
statement: 'Sign in with Ethereum',
uri: window.location.origin,
version: '1',
chainId: Mainnet.id,
nonce,
});
setSignLoading(true);
console.log('signing message');
signature = await signMessageAsync({ message: msg });
console.log('get signature', signature);
await verifyMessage(msg!, signature!);
message.success('Sign in successfully.');
setSigned(true);
setSignLoading(false);
} catch (error: any) {
message.error(error.message);
setSignLoading(false);
}
}, []);
const { signLoading, signed, signIn, setSigned } = useSwie();

return (
<Space>
Expand Down
67 changes: 67 additions & 0 deletions packages/web3/src/ethereum/demos/siwe/useSwie.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { useCallback, useState } from 'react';
import { Account, useProvider } from '@ant-design/web3';
import { Mainnet } from '@ant-design/web3-wagmi';
import { message } from 'antd';
import { useSignMessage } from 'wagmi';

const DefaultSignInfo = {};

export const useSwie = () => {
const { swie } = useProvider();
const [signLoading, setSignLoading] = useState<boolean>(false);
const { signMessageAsync } = useSignMessage();
const [signed, setSigned] = useState<boolean>(false);

const signIn = useCallback(async (a?: Account) => {
if (!swie) return;

const { getNonce, createMessage, verifyMessage } = swie;

const address = a?.address as `0x${string}`;

if (!address) {
message.error('Please connect wallet first.');
return;
}

// get nonce
const nonce = await getNonce?.(address);
if (!nonce) {
message.error('Failed to get nonce.');
return;
}

let msg: string;
let signature: `0x${string}`;

try {
msg = createMessage({
domain: window.location.hostname,
address,
uri: window.location.origin,
nonce,
// Default config
version: '1',
chainId: Mainnet.id,
});
setSignLoading(true);
console.log('signing message');
signature = await signMessageAsync({ message: msg });
console.log('get signature', signature);
await verifyMessage(msg!, signature!);
message.success('Sign in successfully.');
setSigned(true);
setSignLoading(false);
} catch (error: any) {
message.error(error.message);
setSignLoading(false);
}
}, []);

return {
signLoading,
signed,
signIn,
setSigned,
};
};

0 comments on commit 696de5b

Please sign in to comment.