Skip to content

Commit 35dd9e3

Browse files
committed
Merge remote-tracking branch 'origin/main' into docs/solana-memo
# Conflicts: # pnpm-lock.yaml # vitest.config.mts
2 parents afda5e5 + deb2bdd commit 35dd9e3

File tree

780 files changed

+5451
-5562
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

780 files changed

+5451
-5562
lines changed

.changeset/giant-readers-enjoy.md

-5
This file was deleted.

.dumi/pages/index-cn/index.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import Homepage from '../index/index';
2+
3+
export default Homepage;

.dumirc.ts

+2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ const alias = pkgList.reduce(
4141
// 打开 SSR 的情况下需要配置 wagmi 的别名,因为安装了 18.3.0-canary-c3048aab4-20240326 版本的 react 会导致文档 demo 和 packages 中依赖不同版本的 wagmi(pnpm 的包管理机制的原因),导致出现类似下面这样的错误
4242
// `useConfig` must be used within `WagmiProvider`. Docs: https://wagmi.sh/react/api/WagmiProvider.html Version: [email protected]
4343
wagmi: resolve('./node_modules/wagmi'),
44+
// 指定 antd 版本,避免 antd 多版本下官网 design token 不生效的问题
45+
antd: resolve('./node_modules/antd'),
4446
'@tanstack/react-query': resolve('./node_modules/@tanstack/react-query'),
4547
'@ant-design/cssinjs': resolve('./node_modules/@ant-design/cssinjs'),
4648
}

README-zh_CN.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export default () => {
6363

6464
<a href="https://zan.top?chInfo=ch_antdweb3"><image src="https://mdn.alipayobjects.com/huamei_hsbbrh/afts/img/A*ybcRSrUPqhsAAAAAAAAAAAAADiOMAQ/original" /></a>
6565

66-
ZAN 是一家 Web3 技术服务提供商,提供[节点服务](https://zan.top/home/node-service?chInfo=ch_antdweb3)[测试网水龙头](https://zan.top/faucet?chInfo=ch_antdweb3)[智能合约审计](https://zan.top/home/ai-scan?chInfo=ch_antdweb3)[Web3 安全](https://zan.top/home/know-your-transaction?chInfo=ch_antdweb3)等服务。
66+
ZAN 是一家 Web3 技术服务提供商,提供[节点服务](https://zan.top/home/node-service?chInfo=ch_antdweb3)[测试网水龙头](https://zan.top/faucet?chInfo=ch_antdweb3)[智能合约审计](https://zan.top/home/ai-scan?chInfo=ch_antdweb3)等服务。
6767

6868
## 开发
6969

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export default () => {
6363

6464
<a href="https://zan.top?chInfo=ch_antdweb3"><image src="https://mdn.alipayobjects.com/huamei_hsbbrh/afts/img/A*ybcRSrUPqhsAAAAAAAAAAAAADiOMAQ/original" /></a>
6565

66-
ZAN is a Web3 technology service provider offering [node services](https://zan.top/home/node-service?chInfo=ch_antdweb3), [testnet faucet](https://zan.top/faucet?chInfo=ch_antdweb3), [smart contract auditing](https://zan.top/home/ai-scan?chInfo=ch_antdweb3), [Web3 security](https://zan.top/home/know-your-transaction?chInfo=ch_antdweb3), and other services.
66+
ZAN is a Web3 technology service provider offering [node services](https://zan.top/home/node-service?chInfo=ch_antdweb3), [testnet faucet](https://zan.top/faucet?chInfo=ch_antdweb3), [smart contract auditing](https://zan.top/home/ai-scan?chInfo=ch_antdweb3) and other services.
6767

6868
## Development
6969

docs/course/dev-connect.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ We use [MetaMask](https://metamask.io/) as an example to see how to configure th
115115

116116
export default function Web3() {
117117
return (
118-
- <WagmiWeb3ConfigProvider config={config}>
118+
- <WagmiWeb3ConfigProvider>
119119
+ <WagmiWeb3ConfigProvider
120120
+ eip6963={{
121121
+ autoAddInjectedWallets: true,

docs/course/dev-connect.zh-CN.md

+1-8
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,6 @@ import { WagmiWeb3ConfigProvider } from "@ant-design/web3-wagmi";
7474
- import { Address } from "@ant-design/web3";
7575
+ import { Address, NFTCard } from "@ant-design/web3";
7676

77-
const config = createConfig({
78-
chains: [mainnet],
79-
transports: {
80-
[mainnet.id]: http(),
81-
},
82-
});
83-
8477
export default function Web3() {
8578
return (
8679
<WagmiWeb3ConfigProvider>
@@ -120,7 +113,7 @@ export default function Web3() {
120113

121114
export default function Web3() {
122115
return (
123-
- <WagmiWeb3ConfigProvider config={config}>
116+
- <WagmiWeb3ConfigProvider>
124117
+ <WagmiWeb3ConfigProvider
125118
+ eip6963={{
126119
+ autoAddInjectedWallets: true,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// /components/pay-button.tsx
2+
import React from 'react';
3+
import { ConnectButton, Connector } from '@ant-design/web3';
4+
import { MetaMask, WagmiWeb3ConfigProvider } from '@ant-design/web3-wagmi';
5+
import { Button, Space } from 'antd';
6+
import { createConfig, http } from 'wagmi';
7+
import { arbitrum, mainnet, optimism, polygon } from 'wagmi/chains';
8+
import { injected } from 'wagmi/connectors';
9+
10+
import EvmSignTransaction from './send';
11+
12+
type PayButtonsProps = {
13+
setTokenEcosystem?: (token: string) => void;
14+
tokenEcosystem: string;
15+
signCallback: (signTransfer: (toAddress: string, amount: number) => void) => void;
16+
payCallback: (signTransfer: string, address: string) => void;
17+
onRejectSwitchChain?: (id: number) => void;
18+
};
19+
20+
export const EvmPayButton: React.FC<PayButtonsProps> = ({
21+
setTokenEcosystem,
22+
tokenEcosystem,
23+
signCallback,
24+
payCallback,
25+
onRejectSwitchChain,
26+
}) => {
27+
const config = createConfig({
28+
chains: [mainnet, polygon, arbitrum, optimism],
29+
transports: {
30+
[mainnet.id]: http(),
31+
[polygon.id]: http(),
32+
[arbitrum.id]: http(),
33+
[optimism.id]: http(),
34+
},
35+
connectors: [
36+
injected({
37+
target: 'metaMask',
38+
}),
39+
],
40+
});
41+
42+
return (
43+
<div>
44+
<WagmiWeb3ConfigProvider
45+
config={config}
46+
eip6963={{
47+
autoAddInjectedWallets: true,
48+
}}
49+
wallets={[MetaMask()]}
50+
chains={[mainnet, polygon, arbitrum, optimism]}
51+
>
52+
<Space size="middle">
53+
<Connector
54+
modalProps={{
55+
footer: (
56+
<>
57+
Powered by{' '}
58+
<a href="https://web3.ant.design/" target="_blank" rel="noreferrer">
59+
Ant Design Web3
60+
</a>
61+
</>
62+
),
63+
}}
64+
>
65+
<ConnectButton chainSelect={false} />
66+
</Connector>
67+
<EvmSignTransaction
68+
setTokenEcosystem={setTokenEcosystem}
69+
tokenEcosystem={tokenEcosystem}
70+
signTransaction={(signTransfer, address) => {
71+
payCallback(signTransfer, address);
72+
}}
73+
onRejectSwitchChain={onRejectSwitchChain}
74+
renderSignButton={(signTransfer, disabled, signLoading) => (
75+
<Button
76+
type="primary"
77+
style={{ width: 200 }}
78+
loading={signLoading}
79+
disabled={disabled}
80+
onClick={() => {
81+
signCallback(signTransfer);
82+
}}
83+
>
84+
Pay
85+
</Button>
86+
)}
87+
/>
88+
</Space>
89+
</WagmiWeb3ConfigProvider>
90+
</div>
91+
);
92+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// /components/select.tsx
2+
import React from 'react';
3+
import { Radio, Space } from 'antd';
4+
5+
import { TOKEN_PAY_ADDRESS } from '../constants/tokenPayAddress';
6+
7+
interface ChainSelectGroupProps {
8+
ecosystem: string;
9+
onChange: (ecosystem: string) => void;
10+
}
11+
12+
const ChainSelect: React.FC<ChainSelectGroupProps> = (props) => {
13+
const chainList = TOKEN_PAY_ADDRESS.chains;
14+
15+
return (
16+
<Space size="middle">
17+
<Radio.Group
18+
onChange={(e) => {
19+
props.onChange(e.target.value);
20+
}}
21+
value={props.ecosystem}
22+
>
23+
{chainList.map((info) => {
24+
return (
25+
<Radio key={info.ecosystem} value={info.ecosystem}>
26+
{info.name}
27+
</Radio>
28+
);
29+
})}
30+
</Radio.Group>
31+
</Space>
32+
);
33+
};
34+
35+
export default ChainSelect;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// /components/send.tsx
2+
import React, { useEffect, useState } from 'react';
3+
import { useAccount } from '@ant-design/web3';
4+
import { parseAbi, parseUnits } from 'viem';
5+
import { useChainId, useSwitchChain, useWriteContract } from 'wagmi';
6+
7+
import { TOKEN_PAY_ADDRESS } from '../constants/tokenPayAddress';
8+
9+
type SignTransactionProps = {
10+
setTokenEcosystem?: (token: string) => void;
11+
tokenEcosystem: string;
12+
signTransaction: (signTransfer: string, address: string) => void;
13+
renderSignButton: (
14+
signTransfer: (toAddress: string, amount: number) => void,
15+
disabled: boolean,
16+
loading: boolean,
17+
) => React.ReactNode;
18+
onRejectSwitchChain?: (id: number) => void;
19+
};
20+
21+
const EvmSignTransaction: React.FC<SignTransactionProps> = ({
22+
setTokenEcosystem,
23+
tokenEcosystem,
24+
signTransaction,
25+
renderSignButton,
26+
onRejectSwitchChain,
27+
}) => {
28+
const [signLoading, setSignLoading] = useState<boolean>(false);
29+
const { writeContractAsync } = useWriteContract();
30+
const { switchChain } = useSwitchChain();
31+
const chainId = useChainId();
32+
const { account } = useAccount();
33+
34+
useEffect(() => {
35+
if (account?.address) {
36+
const chainList = TOKEN_PAY_ADDRESS.chains;
37+
const changeChainId = chainList.find((item) => item.ecosystem === tokenEcosystem)?.id;
38+
if (changeChainId && changeChainId !== chainId) {
39+
switchChain?.(
40+
{ chainId: changeChainId },
41+
{
42+
onError: (error) => {
43+
if (error.message.includes('User rejected')) {
44+
onRejectSwitchChain?.(chainId);
45+
}
46+
},
47+
},
48+
);
49+
}
50+
}
51+
}, [tokenEcosystem, account]);
52+
53+
useEffect(() => {
54+
if (chainId && !tokenEcosystem) {
55+
const chainList = TOKEN_PAY_ADDRESS.chains;
56+
const initTokenEcosystem = chainList.find((item) => item.id === chainId)?.ecosystem;
57+
if (initTokenEcosystem && account) {
58+
setTokenEcosystem?.(initTokenEcosystem);
59+
} else {
60+
setTokenEcosystem?.(chainList[0].ecosystem);
61+
}
62+
}
63+
}, [account]);
64+
65+
const signTransfer = async (toAddress: string, amount: number) => {
66+
try {
67+
setSignLoading(true);
68+
// transfer ABI
69+
// {
70+
// "constant": false,
71+
// "inputs": [
72+
// { "name": "_to", "type": "address" },
73+
// { "name": "_value", "type": "uint256" }
74+
// ],
75+
// "name": "transfer",
76+
// "outputs": [],
77+
// "payable": false,
78+
// "stateMutability": "nonpayable",
79+
// "type": "function"
80+
// },
81+
const decimals = TOKEN_PAY_ADDRESS.chains.find(
82+
(item) => item.ecosystem === tokenEcosystem,
83+
)?.decimals;
84+
const contractAddress = TOKEN_PAY_ADDRESS.chains.find(
85+
(item) => item.ecosystem === tokenEcosystem,
86+
)?.address;
87+
const signTransferHash = await writeContractAsync({
88+
abi: parseAbi(['function transfer(address _to, uint256 _value)']),
89+
address: contractAddress as `0x${string}`,
90+
functionName: 'transfer',
91+
args: [
92+
toAddress.toLocaleLowerCase() as `0x${string}`,
93+
parseUnits(amount.toString(), decimals!),
94+
],
95+
});
96+
setSignLoading(false);
97+
signTransaction?.(signTransferHash, account?.address || '');
98+
} catch (error) {
99+
console.log('error', (error as any).message);
100+
setSignLoading(false);
101+
}
102+
};
103+
104+
return <div>{renderSignButton(signTransfer, !account, signLoading)}</div>;
105+
};
106+
export default EvmSignTransaction;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// /constants/tokenPayAddress.ts
2+
interface TokenInfo {
3+
name: string;
4+
icon: string;
5+
symbol: string;
6+
chains: {
7+
name: string;
8+
id?: number;
9+
decimals: number;
10+
ecosystem: string;
11+
address: string;
12+
txScan?: string;
13+
network?: string;
14+
}[];
15+
}
16+
export const TOKEN_PAY_ADDRESS: TokenInfo = {
17+
name: 'USDT',
18+
icon: 'https://mdn.alipayobjects.com/huamei_hsbbrh/afts/img/A*HkpaQoYlReEAAAAAAAAAAAAADiOMAQ/original',
19+
symbol: 'usdt',
20+
chains: [
21+
{
22+
name: 'Ethereum',
23+
id: 1,
24+
decimals: 6,
25+
ecosystem: 'ethereum',
26+
network: 'mainnet',
27+
txScan: 'https://etherscan.io/tx/',
28+
address: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
29+
},
30+
{
31+
name: 'Polygon',
32+
id: 137,
33+
decimals: 6,
34+
ecosystem: 'polygon',
35+
network: 'polygon',
36+
txScan: 'https://polygonscan.com/tx/',
37+
address: '0xc2132d05d31c914a87c6611c10748aeb04b58e8f',
38+
},
39+
{
40+
name: 'Arbitrum',
41+
id: 42161,
42+
decimals: 6,
43+
ecosystem: 'arbitrum',
44+
network: 'arbitrum',
45+
txScan: 'https://arbiscan.io/tx/',
46+
address: '0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9',
47+
},
48+
{
49+
name: 'Optimism',
50+
id: 10,
51+
decimals: 6,
52+
ecosystem: 'optimism',
53+
network: 'optimism',
54+
txScan: 'https://optimistic.etherscan.io/tx/',
55+
address: '0x94b008aA00579c1307B0EF2c499aD98a8ce58e58',
56+
},
57+
],
58+
};

0 commit comments

Comments
 (0)