Skip to content

Commit 9b72276

Browse files
committed
fix initial network setup and new account setup
1 parent 4064b1d commit 9b72276

File tree

7 files changed

+160
-80
lines changed

7 files changed

+160
-80
lines changed

README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,18 @@ bun run dev
7979

8080
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. I use Firefox during development.
8181

82-
For unknown reasons, NextJs cannot launch the app properly in the very first time. So you need to press `F5` on your keyboard to reload your web browser again after launching the NextJs, so the NextJs can work properly.
82+
If for unknown reasons, NextJs cannot launch the app properly in the very first time. You need to press `F5` on your keyboard to reload your web browser again after launching the NextJs, so the NextJs can work properly.
8383

8484
Initially, the app should use the default web3 provider via Infura API to load the page.
85-
Then you should click on the `Connect to wallet` button on the top of the home page to connect your Web3 Wallet to this app.
85+
86+
Go to your browser wallet to choose the account you want to connect to. Then come back to this app and click on the `Connect to wallet` button on the top of the home page to connect your Web3 Wallet to this app.
87+
88+
Wagmi should prompt you to switch to the correct network with deployed contracts.
89+
If you want to use another account, go to your browser wallet to choose the account you want to connect to. Then come back to this app and click on `Disconnect` then `Connect to Wallet`
8690

8791
Confirm your initial ETH balance and the token balance on the home page. This token is the token address set inside the ERC721 Sales smart contract during its deployment, or you can reset the token address after deployment.
8892

89-
#### If you do not have the token that is accepted by the NFT Sales contract:
93+
#### If you do not have the tokens that is accepted by the NFT Sales contract:
9094

9195
In the dropdown: choose the USDT or TokenX on Ethereum/Other Chain
9296
In the Radio buttons: choose `Mint Tokens To Guest`

components/carousel/CarouselDraggable.tsx

Lines changed: 48 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -5,34 +5,35 @@ import { useEffect, useRef, useState } from "react";
55
import BasicModal from "../modal/basicModal";
66
import { useToast } from "../ui/use-toast";
77
import { Button } from "../ui/button";
8-
import { changeChainType, getBaseURI, getSalesPrices, initializeDefaultProvider, initializeWallet, runAfterRainbowKit, updateAddrs, updateNftArray, updateNftStatus, useWeb3Store } from "@/store/web3Store";
8+
import { changeChainType, getBaseURI, getSalesPrices, initializeDefaultProvider, initializeWallet, updateChain, updateAddrs, updateNftArray, updateNftStatus, useWeb3Store, updateAccount, removeAccount, setupBlockchainData, blockchain } from "@/store/web3Store";
99
import { useShallow } from 'zustand/react/shallow'
1010
import { ConnectButton } from '@rainbow-me/rainbowkit';
1111
import { useAccount, useDisconnect, useNetwork, useSwitchNetwork } from "wagmi";
12-
import { capitalizeFirst } from "@/lib/utils";
12+
import { capitalizeFirst, delayFunc } from "@/lib/utils";
1313
import { handleAccountsChanged, handleChainChanged } from "@/lib/actions/ethers";
1414

1515
const CARD_HEIGHT = 350;
1616
const MARGIN = 20;
17-
17+
//TODO: https://sepolia.etherscan.io/tx/TXNHASH
18+
//TODO: has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource
1819
export const CarouselDraggable = () => {
1920
const compoName = 'CarouselDraggable'
2021
const lg = console.log;
2122
//const [ref, { width }] = useMeasure();ref={ref}
2223
//lg("width=" + width)
2324
const [leftLimit, setLeftLimit] = useState(0);
25+
//const [mesg, setMesg] = useState('');
2426
const carousel = useRef<HTMLDivElement>(null);
2527
const effectRan = useRef(false)
2628
const { toast } = useToast();
2729
const { disconnect } = useDisconnect()
2830

29-
const { account, isInitialized, isDefaultProvider, nftArray, nftStatuses, prices, baseURI, chainName, nativeAssetName, nativeAssetSymbol, tokenName, tokenSymbol, err } = useWeb3Store(
31+
const { chainType, account, isInitialized, isDefaultProvider, nftArray, nftStatuses, prices, baseURI, chainName, previousChain, nativeAssetName, nativeAssetSymbol, tokenName, tokenSymbol, nftOriginalOwner, nftAddr, salesAddr, err } = useWeb3Store(
3032
useShallow((state) => ({ ...state }))
3133
)
3234
//TODO: disconnect then reconnect => should auto check balances
3335
//lg(compoName + '... effectRan.current:', effectRan.current, ' isDefaultProvider:', isDefaultProvider)
3436
//lg(compoName+ ' account:', account, "nftStatuses:", nftStatuses)
35-
const blockchain = (process.env.NEXT_PUBLIC_BLOCKCHAIN || '').toLowerCase();
3637
useEffect(() => {
3738
lg(compoName + " useEffect runs, blockchain:", blockchain)
3839
if (blockchain || effectRan.current === true) {
@@ -53,38 +54,14 @@ export const CarouselDraggable = () => {
5354
toast({ description: `Failed: ${JSON.stringify(initOut.warn)}`, variant: 'destructive' })
5455
return true;
5556
}
56-
toast({ description: "web3 initialized with the DefaultProvider!" });
57-
lg("initOut:", initOut)
58-
59-
const nftsOut = await updateNftArray(nftIdMin, nftIdMax);
60-
if (nftsOut.err) {
61-
console.error("nftsOut.err:", nftsOut.err)
62-
toast({ description: `${nftsOut.err}`, variant: 'destructive' })
63-
return;
64-
}
65-
66-
const { nftAddr, salesAddr, nftOriginalOwner, err: updateAddrsErr } = await updateAddrs(chainType);
67-
if (updateAddrsErr) {
68-
console.error("updateAddrsErr:", updateAddrsErr)
69-
toast({ description: `${updateAddrsErr}`, variant: 'destructive' })
70-
return;
71-
}
72-
73-
const out2 = await getSalesPrices(chainType, nftsOut.nftIds, nftAddr, salesAddr);
74-
if (out2.err) {
75-
console.error("getSalesPrices err:", out2.err)
76-
toast({ description: `${out2.err}`, variant: 'destructive' })
57+
const out = await setupBlockchainData(nftIdMin, nftIdMax, chainType);
58+
if (out.err) {
59+
toast({ description: `${out.err}`, variant: 'destructive' })
7760
return;
7861
}
79-
await getBaseURI(chainType, nftAddr);
8062

81-
const statuses = await updateNftStatus(chainType, account, nftOriginalOwner, nftAddr, salesAddr, nftIdMin, nftIdMax);
82-
if (statuses.err) {
83-
console.error("updateNftStatus err:", statuses.err)
84-
toast({ description: `${statuses.err}`, variant: 'destructive' })
85-
return;
86-
}
87-
lg("statuses:", statuses.arr)
63+
toast({ description: "web3 initialized with the DefaultProvider on " + capitalizeFirst(initOut.chainName) });
64+
lg("initOut:", initOut)
8865
}
8966
if (isDefaultProvider) {
9067
lg("isDefaultProvider already true")
@@ -98,29 +75,50 @@ export const CarouselDraggable = () => {
9875
}
9976
}, []);
10077

101-
//RainbowKit functions: to detect connected account and chain details
102-
//const { address, isConnecting, isDisconnected } = useAccount();
10378
const { chain, chains } = useNetwork()
79+
if (chain) {
80+
//lg(`Wagmi() useNetwork(): ${chain.name}, chainId: ${chain.id}, previousChain: ${previousChain}`)
81+
//NOT run useState as it will cause loop rendering!
82+
const { decimals: nativeAssetDecimals, name: nativeAssetName, symbol: nativeAssetSymbol } = chain.nativeCurrency;
83+
84+
//this chain IS onConnect! https://wagmi.sh/react/hooks/useNetwork
85+
if (previousChain !== chain.name) {
86+
const run = async () => {
87+
const out1 = await updateChain(chain.name, chain.id, nativeAssetName, nativeAssetSymbol, nativeAssetDecimals)
88+
89+
const out = await setupBlockchainData(nftIdMin, nftIdMax, out1.chainType);
90+
if (out.err) {
91+
toast({ description: `${out.err}`, variant: 'destructive' })
92+
return;
93+
}
94+
}
95+
run();
96+
}
97+
}
98+
10499
const accountRB = useAccount({
105100
onConnect({ address, connector, isReconnected }) {
106-
lg('Connected', address, connector, ', isReconnected:', isReconnected)
107-
if (chain && address) {
108-
lg(`Wagmi()... Connected to ${chain.name}, chainId: ${chain.id}`)
109-
const { decimals: nativeAssetDecimals, name: nativeAssetName, symbol: nativeAssetSymbol } = chain.nativeCurrency;
110-
111-
window.ethereum.on('chainChanged', () => {
112-
disconnect()
113-
window.location.reload();
114-
});
115-
window.ethereum.on('accountsChanged', handleAccountsChanged);
101+
lg('Wagmi useAccount onConnect', address, connector, ', isReconnected:', isReconnected)
102+
if (address) {
103+
const run = async () => {
104+
await updateAccount(address)
116105

117-
if (chain.name.toLowerCase() !== blockchain) {
118-
toast({ description: `Failed: connected chain is not expected! Click on the Network dropdown button, and click on ${capitalizeFirst(blockchain)}. Click on your account dropdown, then click on Disconnect. Then connect wallet again.`, variant: 'destructive' })
119-
return true;
106+
await delayFunc(2000);//wait for statemanagement to update the data to be used below
107+
lg('nftOriginalOwner:', nftOriginalOwner)
108+
const statuses = await updateNftStatus(chainType, address, nftOriginalOwner, nftAddr, salesAddr, nftIdMin, nftIdMax);
109+
if (statuses.err) {
110+
console.error("updateNftStatus err:", statuses.err)
111+
return;
112+
}
113+
lg("statuses:", statuses.arr)
120114
}
121-
runAfterRainbowKit(chain.name, chain.id, address, nativeAssetName, nativeAssetSymbol, nativeAssetDecimals)
115+
run();
122116
}
123117
},
118+
onDisconnect() {
119+
console.log('Account disconnected')
120+
removeAccount()
121+
},
124122
})
125123

126124
const connectToWallet = async () => {

constants/site_data.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { parseIntSafe } from "@/lib/utils";
22

33
export const APP_WIDTH_MIN = 350;
44
export const chainTypeDefault = 'evm';
5-
export const localChainDefault = 'anvil';
5+
export const localChainDefault = 'Foundry'.toLowerCase();
66
export const nftIdMin = 0;
77
export const nftIdMax = 9;
88
export type DragonT = {

lib/actions/ethers.ts

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@ export const erc721JSON = contractsJSON[1];
77
export const salesJSON = contractsJSON[2];
88
export const ArrayOfStructsJSON = contractsJSON[3];
99
import { arrayRange, asyncFor, capitalizeFirst, isEmpty, isEqualStr, parseFloatSafe } from "@/lib/utils";
10-
import { Web3InitOutT, balancesT, initBalancesDefault, web3InitDefault } from "@/store/web3Store";
10+
import { Web3InitOutT, balancesT, blockchain, initBalancesDefault, web3InitDefault } from "@/store/web3Store";
1111
import { localChainDefault } from "@/constants/site_data";
1212

1313
const infuraApiKey = process.env.NEXT_PUBLIC_INFURA_APIKEY || '';
14-
const blockchain = (process.env.NEXT_PUBLIC_BLOCKCHAIN)?.toLowerCase() || localChainDefault.toLowerCase();
1514
const erc20_usdtAddr = process.env.NEXT_PUBLIC_ETHEREUM_USDT || erc20JSON.contractAddress;
1615
const erc20_usdcAddr = process.env.NEXT_PUBLIC_ETHEREUM_USDC || '';
1716
const erc721Addr = process.env.NEXT_PUBLIC_ETHEREUM_NFT || erc721JSON.contractAddress;
@@ -45,7 +44,8 @@ export const ethersDefaultProvider = async (): Promise<Web3InitOutT> => {
4544
let chainId = '', chainName = '', endpoint = ''
4645

4746
const infuraChains = ['mainnet', 'sepolia', 'goerli', 'linea-goerli', 'polygon-mainnet', 'polygon-mumbai', 'optimism-mainnet', 'optimism-goerli', 'arbitrum-mainnet', 'arbitrum-goerli', 'avalanche-mainnet', 'avalanche-fuji', 'starknet-goerli'];
48-
if (blockchain === localChainDefault) {
47+
lg("blockchain:", blockchain)
48+
if (blockchain === localChainDefault.toLowerCase()) {
4949
lg('------ Connect to a local network');
5050
endpoint = "http://localhost:8545";
5151
provider = new ethers.JsonRpcProvider(endpoint);
@@ -63,7 +63,13 @@ export const ethersDefaultProvider = async (): Promise<Web3InitOutT> => {
6363
endpoint = "https://" + blockchain + ".infura.io/v3/" + infuraApiKey;
6464
lg("Use read-only defaults on " + blockchain)
6565
//lg("endpoint:" + endpoint, ', infuraApiKey:', infuraApiKey);
66-
provider = new ethers.InfuraProvider(blockchain, infuraApiKey);
66+
try {
67+
provider = new ethers.InfuraProvider(blockchain, infuraApiKey);
68+
} catch (err) {
69+
mesg = `Error @InfuraProvider. blockchain: ${blockchain}, err:${err}`
70+
console.error(mesg);
71+
return { ...web3InitDefault, err: mesg };
72+
}
6773
//new AlchemyProvider(network, apiKey)
6874
//new QuickNodeProvider(network, token)
6975
chainName = blockchain;
@@ -101,29 +107,50 @@ export const initEvmWalletAfterLoad = async () =>
101107
return { ...web3InitDefault, err: err.message };
102108
}
103109
});
104-
export const afterWagmi = async (): Promise<Web3InitOutT> => {
105-
const funcName = "initializeEvmWallet";
110+
export const setupProvider = async (): Promise<Web3InitOutT> => {
111+
const funcName = "setupProvider";
106112
lg(funcName + "()...");
107113
provider = new ethers.BrowserProvider(window.ethereum)
114+
lg(funcName + " ran successfully")
115+
return {
116+
...web3InitDefault,
117+
};
118+
}
119+
export const setupSigner = async (): Promise<Web3InitOutT> => {
120+
const funcName = "setupSigner";
121+
lg(funcName + "()...");
108122
signer = await provider.getSigner();
109123
lg(funcName + " ran successfully")
110124
return {
111125
...web3InitDefault,
112126
};
113127
}
128+
export const removeSigner = async (): Promise<Web3InitOutT> => {
129+
const funcName = "removeSigner";
130+
lg(funcName + "()...");
131+
signer = undefined;
132+
return {
133+
...web3InitDefault,
134+
};
135+
}
114136
export const initializeEvmWallet = async (): Promise<Web3InitOutT> => {
115137
const funcName = "initializeEvmWallet";
116138
lg(funcName + "()...");
117139
if (window.ethereum == null) {
118140
// If MetaMask is not installed, we use the default provider, which is backed by a variety of third-party services (such as INFURA). They do not have private keys installed so are only have read-only access
119-
warning = "MetaMask not installed; using read-only defaults on sepolia test network";
141+
warning = `MetaMask not installed; using read-only defaults on ${blockchain} test network`;
120142
console.warn(warning)
121-
provider = ethers.getDefaultProvider("sepolia");
143+
try {
144+
provider = ethers.getDefaultProvider(blockchain);
145+
} catch (err) {
146+
console.error('Error getting default provider')
147+
return { ...web3InitDefault, err: 'failed to get default provider' };
148+
}
122149
return {
123150
...web3InitDefault,
124151
warn: warning,
125-
chainId: '11155111',//sepolia
126-
chainName: 'sepolia',
152+
chainId: getChainObj(blockchain).chainId,
153+
chainName: blockchain,
127154
};
128155
} else {
129156
// Connect to the MetaMask EIP-1193 object. This is a standard protocol that allows Ethers access to make all read-only requests through MetaMask.
@@ -942,7 +969,7 @@ export const getEvmAddr = (ctrtName: addrName): string => {
942969
export const getDecimals = (addr: string) => {
943970
//lg('getDecimals. addr:', addr, "erc20JSON.contractAddress:", erc20JSON.contractAddress, isEqualStr(addr, erc20JSON.contractAddress), ', blockchain:', blockchain)
944971
let decimals = 18;
945-
if (blockchain === localChainDefault) {
972+
if (blockchain === localChainDefault.toLowerCase()) {
946973
switch (addr) {
947974
case erc20JSON.contractAddress:
948975
decimals = 6;

lib/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ export const parseIntSafe = (input: any) => {
7676
return out;
7777
}
7878

79-
export const delayFunc = (delay: number): Promise<boolean> => new Promise((resolve, reject) => setTimeout(() => {
79+
export const delayFunc = async (delay: number): Promise<boolean> => new Promise((resolve, reject) => setTimeout(() => {
8080
console.log("delay:", delay);
8181
resolve(true)
8282
}, delay))

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"private": true,
55
"scripts": {
66
"dev": "cp .env.dev .env.local && next dev",
7+
"dev2": "cp .env.prod .env.local && next dev",
78
"buildlocal": "cp .env.prod .env.local && next build",
89
"build": "next build",
910
"start": "next start",

0 commit comments

Comments
 (0)