Skip to content

Commit

Permalink
feat: support multi chain
Browse files Browse the repository at this point in the history
  • Loading branch information
veeso committed Jan 12, 2024
1 parent b534881 commit c404976
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 39 deletions.
4 changes: 2 additions & 2 deletions app/src/js/components/AppLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import * as React from 'react';

import Container from './reusable/Container';
import Page from './reusable/Page';
import MetamaskConnect, { ChainId } from './MetamaskConnect';
import MetamaskConnect from './MetamaskConnect';
import Form from './Form/Form';

const AppLayout = () => (
<Page.BlankPage>
<Container.FlexRow className="justify-between items-center py-4 bg-brand px-4">
<span className="text-xl text-white">NFT WebUI</span>
<MetamaskConnect chainId={ChainId.Goerli} />
<MetamaskConnect />
</Container.FlexRow>
<Container.PageContent className="py-8">
<Form />
Expand Down
5 changes: 3 additions & 2 deletions app/src/js/components/Form/Balance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ import { useConnectedMetaMask, useMetaMask } from 'metamask-react';
import Web3Client from '../../web3/Web3Client';
import Container from '../reusable/Container';
import Heading from '../reusable/Heading';
import { ChainId } from '../MetamaskConnect';

const Balance = () => {
const { account, ethereum } = useConnectedMetaMask();
const { account, ethereum, chainId } = useConnectedMetaMask();
const [balance, setBalance] = React.useState(0);

React.useEffect(() => {
const client = new Web3Client(account, ethereum);
const client = new Web3Client(account, ethereum, chainId as ChainId);
client.balanceOf(account).then((balance) => {
setBalance(balance);
});
Expand Down
9 changes: 5 additions & 4 deletions app/src/js/components/Form/ChangeOwner/ChangeOwnerForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import Input from '../../reusable/Input';
import Button from '../../reusable/Button';
import Web3Client from '../../../web3/Web3Client';
import Alerts from '../../reusable/Alerts';
import { ChainId } from '../../MetamaskConnect';

const ChangeOwnerForm = () => {
const { account, ethereum } = useConnectedMetaMask();
const { account, ethereum, chainId } = useConnectedMetaMask();
const [newOwner, setNewOwner] = React.useState('');
const [pendingTx, setPendingTx] = React.useState<boolean>(false);
const [error, setError] = React.useState<string>();
Expand All @@ -20,7 +21,7 @@ const ChangeOwnerForm = () => {

const onTransfer = () => {
setPendingTx(true);
const client = new Web3Client(account, ethereum);
const client = new Web3Client(account, ethereum, chainId as ChainId);
client
.transferOwnership(newOwner)
.then(() => {
Expand All @@ -44,13 +45,13 @@ const ChangeOwnerForm = () => {
onChange={onNewOwnerChanged}
value={newOwner}
/>
<Button.Primary
<Button.Danger
disabled={btnDisabled}
onClick={onTransfer}
className="!mt-4"
>
Transfer ownership
</Button.Primary>
</Button.Danger>
{error && (
<Alerts.Danger>
<p>{error}</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@ import Heading from '../../reusable/Heading';
import Button from '../../reusable/Button';
import Web3Client from '../../../web3/Web3Client';
import Alerts from '../../reusable/Alerts';
import { ChainId } from '../../MetamaskConnect';

const RenounceOwnershipForm = () => {
const { account, ethereum } = useConnectedMetaMask();
const { account, ethereum, chainId } = useConnectedMetaMask();
const [pendingTx, setPendingTx] = React.useState<boolean>(false);
const [error, setError] = React.useState<string>();

const onTransfer = () => {
setPendingTx(true);
const client = new Web3Client(account, ethereum);
const client = new Web3Client(account, ethereum, chainId as ChainId);
client
.renounceOwnership()
.then(() => {
Expand Down
9 changes: 5 additions & 4 deletions app/src/js/components/Form/Transfer/TransferForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import Input from '../../reusable/Input';
import Button from '../../reusable/Button';
import Web3Client from '../../../web3/Web3Client';
import Alerts from '../../reusable/Alerts';
import { ChainId } from '../../MetamaskConnect';

const TransferForm = () => {
const { account, ethereum } = useConnectedMetaMask();
const { account, ethereum, chainId } = useConnectedMetaMask();
const [recipientAddress, setRecipientAddress] = React.useState('');
const [amount, setAmount] = React.useState('');
const [pendingTx, setPendingTx] = React.useState<boolean>(false);
Expand All @@ -27,7 +28,7 @@ const TransferForm = () => {

const onMint = () => {
setPendingTx(true);
const client = new Web3Client(account, ethereum);
const client = new Web3Client(account, ethereum, chainId as ChainId);

const amoutNum = Number(amount);

Expand Down Expand Up @@ -61,9 +62,9 @@ const TransferForm = () => {
onChange={onAmountChange}
value={amount}
/>
<Button.Danger disabled={btnDisabled} onClick={onMint} className="!mt-4">
<Button.Primary disabled={btnDisabled} onClick={onMint} className="!mt-4">
Transfer
</Button.Danger>
</Button.Primary>
{error && (
<Alerts.Danger>
<p>{error}</p>
Expand Down
65 changes: 43 additions & 22 deletions app/src/js/components/MetamaskConnect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import * as React from 'react';
import { useMetaMask } from 'metamask-react';
import Logo from './MetamaskConnect/Logo';
import Button from './reusable/Button';
import Container from './reusable/Container';
import Select from './reusable/Select';

export enum ChainId {
Mainnet = '0x1',
Expand All @@ -11,23 +13,25 @@ export enum ChainId {
Kovan = '0x2a',
}

interface Props {
chainId: ChainId;
}
const MetamaskConnect = () => {
const [chainId, setChainId] = React.useState<ChainId>();

const MetamaskConnect = ({ chainId: configChainId }: Props) => {
const { status, connect, account, chainId, switchChain } = useMetaMask();
const disabled = [
'initializing',
'unavailable',
'connecting',
'connected',
].includes(status);
const {
status,
connect,
account,
chainId: currentChainId,
switchChain,
} = useMetaMask();
const disabled =
['initializing', 'unavailable', 'connecting', 'connected'].includes(
status,
) || !chainId;

const onClick = () => {
if (status === 'notConnected') {
if (chainId !== configChainId) {
switchChain(configChainId);
if (status === 'notConnected' && chainId) {
if (chainId !== currentChainId) {
switchChain(chainId);
}
return connect();
}
Expand All @@ -50,14 +54,31 @@ const MetamaskConnect = ({ chainId: configChainId }: Props) => {
};

return (
<Button.Alternative
className="my-0 !mb-0"
onClick={onClick}
disabled={disabled}
>
<Logo />
{text()}
</Button.Alternative>
<Container.FlexRow className="items-center gap-8">
<Select
id="metamask-chainid-select"
label="Network"
className="text-white text"
value={chainId}
onChange={(e) => setChainId(e.target.value as ChainId)}
>
{!chainId && (
<option value="" selected>
Select a network
</option>
)}
<option value={ChainId.Mainnet}>Mainnet</option>
<option value={ChainId.Goerli}>Goerli</option>
</Select>
<Button.Alternative
className="my-0 !mb-0"
onClick={onClick}
disabled={disabled}
>
<Logo />
{text()}
</Button.Alternative>
</Container.FlexRow>
);
};

Expand Down
33 changes: 33 additions & 0 deletions app/src/js/components/reusable/Select.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import * as React from 'react';
import Container from './Container';

interface Props {
id: string;
className?: string;
selectClassName?: string;
disabled?: boolean;
label?: string;
onChange?: (e: React.ChangeEvent<HTMLSelectElement>) => void;
value?: string;
children: React.ReactNode;
}

const Select = (props: Props) => (
<Container.Container className={`${props.className} mb-6`}>
{props.label && (
<label htmlFor={props.id} className="block mb-2 font-medium text-text">
{props.label}
</label>
)}
<select
id={props.id}
value={props.value}
onChange={props.onChange}
className={`${props.selectClassName} bg-gray-50 border border-gray-300 text-brand text-sm rounded-lg focus:ring-gray-500 focus:border-gray-500 block w-full p-2.5`}
>
{props.children}
</select>
</Container.Container>
);

export default Select;
7 changes: 5 additions & 2 deletions app/src/js/web3/Web3Client.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import Web3 from 'web3';

import { ABI, CONTRACT_ADDRESS } from './contracts/MyToken';
import { ChainId } from '../components/MetamaskConnect';

export default class Web3Client {
private address: string;
private web3: Web3;
private chainId: ChainId;

constructor(address: string, ethereum: any) {
constructor(address: string, ethereum: any, chainId: ChainId) {
this.address = address;
this.web3 = new Web3(ethereum);
this.chainId = chainId;
}

async transferOwnership(newAddress: string) {
Expand Down Expand Up @@ -36,6 +39,6 @@ export default class Web3Client {
}

private getContract() {
return new this.web3.eth.Contract(ABI, CONTRACT_ADDRESS);
return new this.web3.eth.Contract(ABI, CONTRACT_ADDRESS[this.chainId]);
}
}
18 changes: 17 additions & 1 deletion app/src/js/web3/contracts/MyToken.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { ChainId } from '../../components/MetamaskConnect';

export const ABI = [
{
inputs: [
Expand Down Expand Up @@ -414,4 +416,18 @@ export const ABI = [
},
];

export const CONTRACT_ADDRESS = '0xa0647F0Da8B541C8876C234Bc9C4dC50F19515ea';
interface ContractAddress {
[ChainId.Goerli]: string;
[ChainId.Kovan]: string;
[ChainId.Mainnet]: string;
[ChainId.Rinkeby]: string;
[ChainId.Ropsten]: string;
}

export const CONTRACT_ADDRESS: ContractAddress = {
[ChainId.Goerli]: '0x5FbDB2315678afecb367f032d93F642f64180aa3',
[ChainId.Kovan]: '0x5FbDB2315678afecb367f032d93F642f64180aa3',
[ChainId.Mainnet]: '0xa0647F0Da8B541C8876C234Bc9C4dC50F19515ea',
[ChainId.Rinkeby]: '0x5FbDB2315678afecb367f032d93F642f64180aa3',
[ChainId.Ropsten]: '0x5FbDB2315678afecb367f032d93F642f64180aa3',
};

0 comments on commit c404976

Please sign in to comment.