-
Notifications
You must be signed in to change notification settings - Fork 152
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: Payment In USDT * fix: add translate * fix: Flex to Space * fix: EvmPayButtons -> EvmPayButton * fix: Add chainSelect argument * Update .changeset/kind-eels-press.md * Update docs/guide/payment-in-usdt.zh-CN.md Co-authored-by: thinkasany <[email protected]> * Update docs/guide/payment-in-usdt.zh-CN.md Co-authored-by: thinkasany <[email protected]> --------- Co-authored-by: 愚指导 <[email protected]> Co-authored-by: thinkasany <[email protected]>
- Loading branch information
1 parent
703f16a
commit 2ee466c
Showing
13 changed files
with
407 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@ant-design/web3': minor | ||
--- | ||
|
||
feat: Add chainSelect argument |
106 changes: 106 additions & 0 deletions
106
docs/guide/demos/best-practice/components/pay-button.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
// /components/pay-button.tsx | ||
import React from 'react'; | ||
import { ConnectButton, Connector } from '@ant-design/web3'; | ||
import { MetaMask, WagmiWeb3ConfigProvider } from '@ant-design/web3-wagmi'; | ||
import { Button, Space } from 'antd'; | ||
import { createConfig, http } from 'wagmi'; | ||
import { arbitrum, mainnet, optimism, polygon } from 'wagmi/chains'; | ||
import { injected } from 'wagmi/connectors'; | ||
|
||
import EvmSignTransaction from './send'; | ||
|
||
type PayButtonsProps = { | ||
setTokenEcosystem?: (token: string) => void; | ||
tokenEcosystem: string; | ||
signCallback: (signTransfer: (toAddress: string, amount: number) => void) => void; | ||
payCallback: (signTransfer: string, address: string) => void; | ||
onRejectSwitchChain?: (id: number) => void; | ||
}; | ||
|
||
export const EvmPayButton: React.FC<PayButtonsProps> = ({ | ||
setTokenEcosystem, | ||
tokenEcosystem, | ||
signCallback, | ||
payCallback, | ||
onRejectSwitchChain, | ||
}) => { | ||
const config = createConfig({ | ||
chains: [mainnet, polygon, arbitrum, optimism], | ||
transports: { | ||
[mainnet.id]: http(), | ||
[polygon.id]: http(), | ||
[arbitrum.id]: http(), | ||
[optimism.id]: http(), | ||
}, | ||
connectors: [ | ||
injected({ | ||
target: 'metaMask', | ||
}), | ||
], | ||
}); | ||
|
||
return ( | ||
<div> | ||
<WagmiWeb3ConfigProvider | ||
config={config} | ||
eip6963={{ | ||
autoAddInjectedWallets: true, | ||
}} | ||
wallets={[MetaMask()]} | ||
chains={[mainnet, polygon, arbitrum, optimism]} | ||
> | ||
<Space size="middle"> | ||
<Connector | ||
modalProps={{ | ||
footer: ( | ||
<> | ||
Powered by{' '} | ||
<a href="https://web3.ant.design/" target="_blank" rel="noreferrer"> | ||
Ant Design Web3 | ||
</a> | ||
</> | ||
), | ||
}} | ||
> | ||
<ConnectButton chainSelect={false} /> | ||
</Connector> | ||
<Connector | ||
modalProps={{ | ||
footer: ( | ||
<> | ||
Powered by{' '} | ||
<a href="https://web3.ant.design/" target="_blank" rel="noreferrer"> | ||
Ant Design Web3 | ||
</a> | ||
</> | ||
), | ||
}} | ||
> | ||
<ConnectButton chainSelect={false} /> | ||
</Connector> | ||
<EvmSignTransaction | ||
setTokenEcosystem={setTokenEcosystem} | ||
tokenEcosystem={tokenEcosystem} | ||
signTransaction={(signTransfer, address) => { | ||
payCallback(signTransfer, address); | ||
}} | ||
onRejectSwitchChain={onRejectSwitchChain} | ||
renderSignButton={(signTransfer, disabled, signLoading) => ( | ||
<Button | ||
type="primary" | ||
style={{ width: 200 }} | ||
loading={signLoading} | ||
disabled={disabled} | ||
onClick={() => { | ||
signCallback(signTransfer); | ||
}} | ||
> | ||
Pay | ||
</Button> | ||
)} | ||
/> | ||
</Space> | ||
</WagmiWeb3ConfigProvider> | ||
</div> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// /components/select.tsx | ||
import React from 'react'; | ||
import { Radio, Space } from 'antd'; | ||
|
||
import { TOKEN_PAY_ADDRESS } from '../constants/tokenPayAddress'; | ||
|
||
interface ChainSelectGroupProps { | ||
ecosystem: string; | ||
onChange: (ecosystem: string) => void; | ||
} | ||
|
||
const ChainSelect: React.FC<ChainSelectGroupProps> = (props) => { | ||
const chainList = TOKEN_PAY_ADDRESS.chains; | ||
|
||
return ( | ||
<Space size="middle"> | ||
<Radio.Group | ||
onChange={(e) => { | ||
props.onChange(e.target.value); | ||
}} | ||
value={props.ecosystem} | ||
> | ||
{chainList.map((info) => { | ||
return ( | ||
<Radio key={info.ecosystem} value={info.ecosystem}> | ||
{info.name} | ||
</Radio> | ||
); | ||
})} | ||
</Radio.Group> | ||
</Space> | ||
); | ||
}; | ||
|
||
export default ChainSelect; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
// /components/send.tsx | ||
import React, { useEffect, useState } from 'react'; | ||
import { useAccount } from '@ant-design/web3'; | ||
import { parseAbi, parseUnits } from 'viem'; | ||
import { useChainId, useSwitchChain, useWriteContract } from 'wagmi'; | ||
|
||
import { TOKEN_PAY_ADDRESS } from '../constants/tokenPayAddress'; | ||
|
||
type SignTransactionProps = { | ||
setTokenEcosystem?: (token: string) => void; | ||
tokenEcosystem: string; | ||
signTransaction: (signTransfer: string, address: string) => void; | ||
renderSignButton: ( | ||
signTransfer: (toAddress: string, amount: number) => void, | ||
disabled: boolean, | ||
loading: boolean, | ||
) => React.ReactNode; | ||
onRejectSwitchChain?: (id: number) => void; | ||
}; | ||
|
||
const EvmSignTransaction: React.FC<SignTransactionProps> = ({ | ||
setTokenEcosystem, | ||
tokenEcosystem, | ||
signTransaction, | ||
renderSignButton, | ||
onRejectSwitchChain, | ||
}) => { | ||
const [signLoading, setSignLoading] = useState<boolean>(false); | ||
const { writeContractAsync } = useWriteContract(); | ||
const { switchChain } = useSwitchChain(); | ||
const chainId = useChainId(); | ||
const { account } = useAccount(); | ||
|
||
useEffect(() => { | ||
if (account?.address) { | ||
const chainList = TOKEN_PAY_ADDRESS.chains; | ||
const changeChainId = chainList.find((item) => item.ecosystem === tokenEcosystem)?.id; | ||
if (changeChainId && changeChainId !== chainId) { | ||
switchChain?.( | ||
{ chainId: changeChainId }, | ||
{ | ||
onError: (error) => { | ||
if (error.message.includes('User rejected')) { | ||
onRejectSwitchChain?.(chainId); | ||
} | ||
}, | ||
}, | ||
); | ||
} | ||
} | ||
}, [tokenEcosystem, account]); | ||
|
||
useEffect(() => { | ||
if (chainId && !tokenEcosystem) { | ||
const chainList = TOKEN_PAY_ADDRESS.chains; | ||
const initTokenEcosystem = chainList.find((item) => item.id === chainId)?.ecosystem; | ||
if (initTokenEcosystem && account) { | ||
setTokenEcosystem?.(initTokenEcosystem); | ||
} else { | ||
setTokenEcosystem?.(chainList[0].ecosystem); | ||
} | ||
} | ||
}, [account]); | ||
|
||
const signTransfer = async (toAddress: string, amount: number) => { | ||
try { | ||
setSignLoading(true); | ||
// transfer ABI | ||
// { | ||
// "constant": false, | ||
// "inputs": [ | ||
// { "name": "_to", "type": "address" }, | ||
// { "name": "_value", "type": "uint256" } | ||
// ], | ||
// "name": "transfer", | ||
// "outputs": [], | ||
// "payable": false, | ||
// "stateMutability": "nonpayable", | ||
// "type": "function" | ||
// }, | ||
const decimals = TOKEN_PAY_ADDRESS.chains.find( | ||
(item) => item.ecosystem === tokenEcosystem, | ||
)?.decimals; | ||
const contractAddress = TOKEN_PAY_ADDRESS.chains.find( | ||
(item) => item.ecosystem === tokenEcosystem, | ||
)?.address; | ||
const signTransferHash = await writeContractAsync({ | ||
abi: parseAbi(['function transfer(address _to, uint256 _value)']), | ||
address: contractAddress as `0x${string}`, | ||
functionName: 'transfer', | ||
args: [ | ||
toAddress.toLocaleLowerCase() as `0x${string}`, | ||
parseUnits(amount.toString(), decimals!), | ||
], | ||
}); | ||
setSignLoading(false); | ||
signTransaction?.(signTransferHash, account?.address || ''); | ||
} catch (error) { | ||
console.log('error', (error as any).message); | ||
setSignLoading(false); | ||
} | ||
}; | ||
|
||
return <div>{renderSignButton(signTransfer, !account, signLoading)}</div>; | ||
}; | ||
export default EvmSignTransaction; |
58 changes: 58 additions & 0 deletions
58
docs/guide/demos/best-practice/constants/tokenPayAddress.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// /constants/tokenPayAddress.ts | ||
interface TokenInfo { | ||
name: string; | ||
icon: string; | ||
symbol: string; | ||
chains: { | ||
name: string; | ||
id?: number; | ||
decimals: number; | ||
ecosystem: string; | ||
address: string; | ||
txScan?: string; | ||
network?: string; | ||
}[]; | ||
} | ||
export const TOKEN_PAY_ADDRESS: TokenInfo = { | ||
name: 'USDT', | ||
icon: 'https://mdn.alipayobjects.com/huamei_hsbbrh/afts/img/A*HkpaQoYlReEAAAAAAAAAAAAADiOMAQ/original', | ||
symbol: 'usdt', | ||
chains: [ | ||
{ | ||
name: 'Ethereum', | ||
id: 1, | ||
decimals: 6, | ||
ecosystem: 'ethereum', | ||
network: 'mainnet', | ||
txScan: 'https://etherscan.io/tx/', | ||
address: '0xdAC17F958D2ee523a2206206994597C13D831ec7', | ||
}, | ||
{ | ||
name: 'Polygon', | ||
id: 137, | ||
decimals: 6, | ||
ecosystem: 'polygon', | ||
network: 'polygon', | ||
txScan: 'https://polygonscan.com/tx/', | ||
address: '0xc2132d05d31c914a87c6611c10748aeb04b58e8f', | ||
}, | ||
{ | ||
name: 'Arbitrum', | ||
id: 42161, | ||
decimals: 6, | ||
ecosystem: 'arbitrum', | ||
network: 'arbitrum', | ||
txScan: 'https://arbiscan.io/tx/', | ||
address: '0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9', | ||
}, | ||
{ | ||
name: 'Optimism', | ||
id: 10, | ||
decimals: 6, | ||
ecosystem: 'optimism', | ||
network: 'optimism', | ||
txScan: 'https://optimistic.etherscan.io/tx/', | ||
address: '0x94b008aA00579c1307B0EF2c499aD98a8ce58e58', | ||
}, | ||
], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
// /usdt.tsx | ||
import React, { useState } from 'react'; | ||
import { Card, message, Space, Typography } from 'antd'; | ||
|
||
import { EvmPayButton } from './components/pay-button'; | ||
import ChainSelect from './components/select'; | ||
import { TOKEN_PAY_ADDRESS } from './constants/tokenPayAddress'; | ||
|
||
const { Title } = Typography; | ||
|
||
const PaymentInUSDT: React.FC = () => { | ||
// token ecosystem | ||
const [tokenEcosystem, setTokenEcosystem] = useState<string>(''); | ||
|
||
const onSubmitCashier = async (sign: (toAddress: string, amount: number) => void) => { | ||
// The address and amount are obtained from the backend service | ||
sign('0x35ceCD3d51Fe9E5AD14ea001475668C5A5e5ea76', 10); | ||
}; | ||
|
||
const runPay = async (sign: string, address: string) => { | ||
message.success('Pay success'); | ||
}; | ||
|
||
return ( | ||
<Card title="Payment in USDT"> | ||
<Space direction="vertical" size="middle"> | ||
<Title level={3}>Select Chain</Title> | ||
<ChainSelect ecosystem={tokenEcosystem} onChange={setTokenEcosystem} /> | ||
<EvmPayButton | ||
setTokenEcosystem={setTokenEcosystem} | ||
tokenEcosystem={tokenEcosystem} | ||
signCallback={onSubmitCashier} | ||
payCallback={runPay} | ||
onRejectSwitchChain={(id) => { | ||
const oldTokenEcosystem = TOKEN_PAY_ADDRESS.chains.find( | ||
(item) => item.id === id, | ||
)?.ecosystem; | ||
setTokenEcosystem(oldTokenEcosystem || ''); | ||
}} | ||
/> | ||
</Space> | ||
</Card> | ||
); | ||
}; | ||
|
||
export default PaymentInUSDT; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
--- | ||
nav: Payment In USDT | ||
group: Best Practice | ||
--- | ||
|
||
# Payment In USDT | ||
|
||
When your project needs to support `USDT` payments and needs to support `USDT/USDC` on multiple chains, the following can help you. | ||
|
||
You can use our official adapter with `@ant-design/web3` to quickly connect to various blockchains to support `USDT/USDC` payments on these chains at the same time. | ||
|
||
You can do this: | ||
|
||
<code compact src="./demos/best-practice/usdt.tsx"></code> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
--- | ||
nav: 用 USDT 支付 | ||
group: 最佳实践 | ||
--- | ||
|
||
# 用 USDT 支付 | ||
|
||
当你的项目需要支持 `USDT` 付款的时候,并且需要支持多个链的 `USDT` / `USDC` 时,下边这些可以帮到你。 | ||
|
||
你可以通过我们官方提供的适配器配合 `@ant-design/web3` 使用,快速连接各类区块链,以便于同时支持这些链的 `USDT` / `USDC` 支付。 | ||
|
||
你可以这样做: | ||
|
||
<code compact src="./demos/best-practice/usdt.tsx"></code> |
Oops, something went wrong.