Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(wagmi): optimize the implementation of wagmi provider #1003

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/chilled-snails-boil.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@ant-design/web3-assets': minor
'@ant-design/web3-common': minor
'@ant-design/web3-wagmi': minor
'@ant-design/web3': minor
---

refactor(wagmi): optimize the implementation of wagmi provider
1 change: 1 addition & 0 deletions packages/assets/src/wallets/backpack.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { WalletMetadata } from '@ant-design/web3-common';
import { BackpackColorful, ChromeCircleColorful } from '@ant-design/web3-icons';

export const metadata_Backpack: WalletMetadata = {
key: 'app.backpack',
icon: <BackpackColorful />,
name: 'Backpack',
remark: 'Backpack Wallet',
Expand Down
1 change: 1 addition & 0 deletions packages/assets/src/wallets/coinbase-wallet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { WalletMetadata } from '@ant-design/web3-common';
import { ChromeCircleColorful, CoinbaseWalletCircleColorful } from '@ant-design/web3-icons';

export const metadata_CoinbaseWallet: WalletMetadata = {
key: 'com.coinbase.wallet',
icon: <CoinbaseWalletCircleColorful />,
name: 'Coinbase Wallet',
remark: 'Coinbase Wallet',
Expand Down
1 change: 1 addition & 0 deletions packages/assets/src/wallets/meta-mask.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ChainType, type WalletMetadata } from '@ant-design/web3-common';
import { ChromeCircleColorful, MetaMaskColorful } from '@ant-design/web3-icons';

export const metadata_MetaMask: WalletMetadata = {
key: 'io.metamask',
icon: <MetaMaskColorful />,
name: 'MetaMask',
remark: 'MetaMask Wallet',
Expand Down
1 change: 1 addition & 0 deletions packages/assets/src/wallets/okx-wallet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { WalletMetadata } from '@ant-design/web3-common';
import { ChromeCircleColorful, OkxWalletColorful } from '@ant-design/web3-icons';

export const metadata_OkxWallet: WalletMetadata = {
key: 'com.okex.wallet',
icon: <OkxWalletColorful />,
name: 'OKX Wallet',
remark: 'OKX Wallet',
Expand Down
1 change: 1 addition & 0 deletions packages/assets/src/wallets/phantom.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { WalletMetadata } from '@ant-design/web3-common';
import { ChromeCircleColorful, PhantomColorful } from '@ant-design/web3-icons';

export const metadata_Phantom: WalletMetadata = {
key: 'app.phantom',
icon: <PhantomColorful />,
name: 'Phantom',
remark: 'Phantom Wallet',
Expand Down
1 change: 1 addition & 0 deletions packages/assets/src/wallets/safeheron.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { WalletMetadata } from '@ant-design/web3-common';
import { ChromeCircleColorful, SafeheronColorful } from '@ant-design/web3-icons';

export const metadata_Safeheron: WalletMetadata = {
key: 'com.safeheron.wallet',
icon: <SafeheronColorful />,
name: 'Safeheron',
remark: 'Safeheron Wallet',
Expand Down
1 change: 1 addition & 0 deletions packages/assets/src/wallets/token-pocket.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ChainType, type WalletMetadata } from '@ant-design/web3-common';
import { ChromeCircleColorful, TokenPocketColorful } from '@ant-design/web3-icons';

export const metadata_TokenPocket: WalletMetadata = {
key: 'pro.tokenpocket',
icon: <TokenPocketColorful />,
name: 'TokenPocket',
remark: 'TokenPocket',
Expand Down
1 change: 1 addition & 0 deletions packages/assets/src/wallets/trust.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { WalletMetadata } from '@ant-design/web3-common';
import { ChromeCircleColorful, TrustWalletColorful } from '@ant-design/web3-icons';

export const metadata_Trust: WalletMetadata = {
key: 'com.trustwallet.app',
icon: <TrustWalletColorful />,
name: 'Trust',
remark: 'Trust Wallet',
Expand Down
1 change: 1 addition & 0 deletions packages/assets/src/wallets/wallet-connect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { WalletMetadata } from '@ant-design/web3-common';
import { WalletConnectColorful } from '@ant-design/web3-icons';

export const metadata_WalletConnect: WalletMetadata = {
key: 'walletconnect',
icon: <WalletConnectColorful />,
name: 'WalletConnect',
remark: 'Connect with mobile APP',
Expand Down
10 changes: 5 additions & 5 deletions packages/common/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,9 @@ export interface UniversalWeb3ProviderInterface {
}

export interface Wallet extends WalletMetadata {
hasWalletReady?: () => Promise<boolean>;
hasExtensionInstalled?: () => Promise<boolean>;
getQrCode?: () => Promise<{ uri: string }>;
hasWalletReady?: () => boolean | Promise<boolean>;
hasExtensionInstalled?: () => boolean | Promise<boolean>;
getQrCode?: () => { uri: string } | Promise<{ uri: string }>;
}

/**
Expand Down Expand Up @@ -161,8 +161,8 @@ export type WalletMetadata = {
*/
remark: string;
/**
* @desc 钱包的 key
* @descEn The key of Wallet
* @desc 钱包的 key, 一般设置为 EIP6963 中的 RDNS(RFC2397)格式
* @descEn The key of Wallet, generally set to the RDNS (RFC2397) format in EIP6963
*/
key?: React.Key;
/**
Expand Down
14 changes: 8 additions & 6 deletions packages/wagmi/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,22 @@
"dependencies": {
"@ant-design/web3-assets": "workspace:*",
"@ant-design/web3-common": "workspace:*",
"debug": "^4.3.5"
"debug": "^4.3.5",
"lodash-es": "^4.17.21"
},
"devDependencies": {
"@tanstack/react-query": "^5.40.1",
"@types/debug": "^4.1.12",
"@types/lodash-es": "^4.17.12",
"father": "^4.4.4",
"typescript": "^5.5.2",
"wagmi": "^2.10.5",
"@tanstack/react-query": "^5.40.1",
"viem": "^2.15.1"
"viem": "^2.15.1",
"wagmi": "^2.10.5"
},
"peerDependencies": {
"wagmi": "^2.10.5",
"@tanstack/react-query": "^5.40.1",
"viem": ">=2.0.0"
"viem": ">=2.0.0",
"wagmi": "^2.10.5"
},
"publishConfig": {
"registry": "https://registry.npmjs.org",
Expand Down
11 changes: 11 additions & 0 deletions packages/wagmi/src/connectors/define-wallet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { metadata_MetaMask } from '@ant-design/web3-assets';
import type { Wallet, WalletMetadata } from '@ant-design/web3-common';

export const defineWallet = (callback: (metadata: WalletMetadata) => Wallet) => callback;

export const metaMask = defineWallet((m) => {
return {
...metadata_MetaMask,
...m,
};
});
3 changes: 3 additions & 0 deletions packages/wagmi/src/connectors/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './meta-mask';
export * from './okx-wallet';
export * from './trust-wallet';
22 changes: 22 additions & 0 deletions packages/wagmi/src/connectors/meta-mask.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { metadata_MetaMask } from '@ant-design/web3-assets';
import type { WalletMetadata } from '@ant-design/web3-common';
import type { CreateConnectorFn } from 'wagmi';
import { injected, type InjectedParameters } from 'wagmi/connectors';

export const metaMask = (
params: Omit<InjectedParameters, 'target'> & Partial<WalletMetadata> = {},
): CreateConnectorFn => {
const { shimDisconnect, unstable_shimAsyncInject, ...metadataParams } = params;
const metadata = { ...metadataParams, ...metadata_MetaMask };
return injected({
target: {
...metadata,
id: metadata.key || 'injected',
name: metadata.name,
icon: metadata.icon,
provider: window.ethereum,
} as any,
shimDisconnect,
unstable_shimAsyncInject,
});
};
22 changes: 22 additions & 0 deletions packages/wagmi/src/connectors/okx-wallet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { metadata_OkxWallet } from '@ant-design/web3-assets';
import type { WalletMetadata } from '@ant-design/web3-common';
import type { CreateConnectorFn } from 'wagmi';
import { injected, type InjectedParameters } from 'wagmi/connectors';

export const okxWallet = (
params: Omit<InjectedParameters, 'target'> & Partial<WalletMetadata> = {},
): CreateConnectorFn => {
const { shimDisconnect, unstable_shimAsyncInject, ...metadataParams } = params;
const metadata = { ...metadataParams, ...metadata_OkxWallet };
return injected({
target: {
...metadata,
id: metadata.key || 'injected',
name: metadata.name,
icon: metadata.icon,
provider: window.ethereum,
} as any,
shimDisconnect,
unstable_shimAsyncInject,
});
};
22 changes: 22 additions & 0 deletions packages/wagmi/src/connectors/trust-wallet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { metadata_Trust } from '@ant-design/web3-assets';
import type { WalletMetadata } from '@ant-design/web3-common';
import type { CreateConnectorFn } from 'wagmi';
import { injected, type InjectedParameters } from 'wagmi/connectors';

export const turstWallet = (
params: Omit<InjectedParameters, 'target'> & Partial<WalletMetadata> = {},
): CreateConnectorFn => {
const { shimDisconnect, unstable_shimAsyncInject, ...metadataParams } = params;
const metadata = { ...metadataParams, ...metadata_Trust };
return injected({
target: {
...metadata,
id: metadata.key || 'injected',
name: metadata.name,
icon: metadata.icon,
provider: window.ethereum,
} as any,
shimDisconnect,
unstable_shimAsyncInject,
});
};
4 changes: 3 additions & 1 deletion packages/wagmi/src/global.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { EIP1193Provider } from 'viem';

declare interface Window {
ethereum?: any;
ethereum?: EIP1193Provider;
}
5 changes: 5 additions & 0 deletions packages/wagmi/src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './useAccount';
export * from './useBalance';
export * from './useChain';
export * from './useChains';
export * from './useWallets';
29 changes: 29 additions & 0 deletions packages/wagmi/src/hooks/useAccount.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';
import type { Account } from '@ant-design/web3-common';
import { useEnsAvatar, useEnsName, useAccount as useWagmiAccount } from 'wagmi';

export interface UseAccountOptions {
showENS?: boolean;
showAvatar?: boolean;
}

export type UseAccountResult = Account | undefined;

export const useAccount = (options?: UseAccountOptions): UseAccountResult => {
const showENS = options?.showENS ?? true;
const showAvatar = options?.showAvatar ?? true;
const { address, isDisconnected } = useWagmiAccount();
const { data: ensName } = useEnsName({ address: showENS ? address : undefined });
const { data: ensAvatar } = useEnsAvatar({ name: ensName && showAvatar ? ensName : undefined });

const account = React.useMemo<UseAccountResult>(() => {
if (!address || isDisconnected) return undefined;
return {
address,
name: ensName ?? undefined,
avatar: ensAvatar ?? undefined,
};
}, [address, ensAvatar, ensName, isDisconnected]);

return account;
};
30 changes: 30 additions & 0 deletions packages/wagmi/src/hooks/useBalance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react';
import type { Balance } from '@ant-design/web3-common';
import { useAccount, useBalance as useWagmiBalance } from 'wagmi';

import { useChain } from './useChain';

export interface UseBalanceOptions {
showBalance?: boolean;
}

export type UseBalanceResult = Balance | undefined;

export const useBalance = (options?: UseBalanceOptions): UseBalanceResult => {
const showBalance = options?.showBalance ?? true;
const { address } = useAccount();
const { data: balanceData } = useWagmiBalance({
address: address && showBalance ? address : undefined,
});
const chain = useChain();
const balance = React.useMemo<UseBalanceResult>(() => {
if (!balanceData) return undefined;
return {
symbol: balanceData?.symbol,
value: balanceData?.value,
decimals: balanceData?.decimals,
icon: chain?.nativeCurrency?.icon,
};
}, [balanceData, chain]);
return balance;
};
14 changes: 14 additions & 0 deletions packages/wagmi/src/hooks/useChain.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { Chain } from '@ant-design/web3-common';
import { useChainId } from 'wagmi';

import { useChains } from './useChains';

export type UseChainResult = Chain | undefined;

export const useChain = (): UseChainResult => {
const connectedChainId = useChainId();
const availableChains = useChains();
const chain =
availableChains.find((current) => current.id === connectedChainId) ?? availableChains?.[0];
return chain;
};
23 changes: 23 additions & 0 deletions packages/wagmi/src/hooks/useChains.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import * as chainAssets from '@ant-design/web3-assets';
import type { Chain } from '@ant-design/web3-common';
import { merge } from 'lodash-es';
import { useChains as useWagmiChains } from 'wagmi';

const chainIdMap: Record<number, Chain> = Object.fromEntries(
Object.values(chainAssets).map((chainItem: any) => [chainItem?.id, chainItem]),
);

export type UseChainsResult = Chain[];

export const useChains = (): UseChainsResult => {
const chains = useWagmiChains();

// Merge with chainAssets
const availableChains = chains.map<Chain>((current) => {
if (chainIdMap[current.id]?.id === current.id) {
return merge(chainIdMap[current.id], current);
}
return current;
});
return availableChains;
};
42 changes: 42 additions & 0 deletions packages/wagmi/src/hooks/useWallets.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { metadata_MobileConnect } from '@ant-design/web3-assets';
import { Wallet } from '@ant-design/web3-common';
import { useConnectors } from 'wagmi';

export type UseWalletsResult = Wallet[];

export const useWallets = (): UseWalletsResult => {
const connectors = useConnectors();
const walletConnect = connectors.find((current) => current.id === 'walletConnect');
const getQrCode = async () =>
new Promise<{ uri: string }>((resolve) =>
walletConnect?.emitter.on('message', ({ type, data }) => {
if (type === 'display_uri') resolve({ uri: data as string });
}),
);
const wallets = connectors.map<Wallet>((connector) => {
// For wallet-connect protocol
if (connector === walletConnect) {
return {
...metadata_MobileConnect,
key: walletConnect?.uid,
getWagmiConnector: () => walletConnect,
hasWalletReady: () => true,
getQrCode: walletConnect ? getQrCode : undefined,
};
}

// For eip6963 standard wallets
return {
icon: connector?.icon,
name: connector!.name,
remark: `Wallet ${connector?.name} detected`,
key: connector?.uid,
hasWalletReady: () => !!connector.uid,
hasExtensionInstalled: () => true,
getQrCode: walletConnect ? getQrCode : undefined,
group: 'Installed',
};
});

return wallets;
};
4 changes: 3 additions & 1 deletion packages/wagmi/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export * from './wagmi-provider';
export * from './provider';
export * from './wallets';
export * from './interface';
export * from '@ant-design/web3-assets';

export * as connectors from './connectors';
2 changes: 2 additions & 0 deletions packages/wagmi/src/provider/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './pure-config-provider';
export * from './web3-config-provider';
Loading
Loading