diff --git a/packages/commonwealth/client/scripts/controllers/app/webWallets/coinbase_web_wallet.ts b/packages/commonwealth/client/scripts/controllers/app/webWallets/coinbase_web_wallet.ts index 491681742ed..06db60a40e8 100644 --- a/packages/commonwealth/client/scripts/controllers/app/webWallets/coinbase_web_wallet.ts +++ b/packages/commonwealth/client/scripts/controllers/app/webWallets/coinbase_web_wallet.ts @@ -94,12 +94,12 @@ class CoinbaseWebWalletController implements IWebWallet { } // ACTIONS - public async enable() { + public async enable(forceChainId?: string) { console.log('Attempting to enable Coinbase'); this._enabling = true; try { // default to ETH - const chainId = this.getChainId(); + const chainId = forceChainId ?? this.getChainId(); // ensure we're on the correct chain @@ -199,43 +199,36 @@ class CoinbaseWebWalletController implements IWebWallet { ); } - public async switchNetwork() { + public async switchNetwork(chainId?: string) { try { // Get current chain ID - const currentChainId = await this._web3.eth.getChainId(); - const communityChain = this.getChainId(); - const chainIdHex = `0x${parseInt(communityChain, 10).toString(16)}`; - if (currentChainId !== communityChain) { - try { - await window.ethereum.request({ - method: 'wallet_switchEthereumChain', - params: [{ chainId: `0x${chainIdHex}` }], + const communityChain = chainId ?? this.getChainId(); + const chainIdHex = parseInt(communityChain, 10).toString(16); + try { + await window.ethereum.request({ + method: 'wallet_switchEthereumChain', + params: [{ chainId: `0x${chainIdHex}` }], + }); + } catch (error) { + if (error.code === 4902) { + const chains = await $.getJSON('https://chainid.network/chains.json'); + const baseChain = chains.find((c) => c.chainId === communityChain); + // Check if the string contains '${' and '}' + const rpcUrl = baseChain.rpc.filter((r) => !/\${.*?}/.test(r)); + const url = + rpcUrl.length > 0 ? rpcUrl[0] : app.chain.meta.node.altWalletUrl; + await this._web3.givenProvider.request({ + method: 'wallet_addEthereumChain', + params: [ + { + chainId: chainIdHex, + chainName: baseChain.name, + nativeCurrency: baseChain.nativeCurrency, + rpcUrls: [url], + }, + ], }); - } catch (error) { - if (error.code === 4902) { - const chains = await $.getJSON( - 'https://chainid.network/chains.json', - ); - const baseChain = chains.find((c) => c.chainId === communityChain); - // Check if the string contains '${' and '}' - const rpcUrl = baseChain.rpc.filter((r) => !/\${.*?}/.test(r)); - const url = - rpcUrl.length > 0 ? rpcUrl[0] : app.chain.meta.node.altWalletUrl; - await this._web3.givenProvider.request({ - method: 'wallet_addEthereumChain', - params: [ - { - chainId: chainIdHex, - chainName: baseChain.name, - nativeCurrency: baseChain.nativeCurrency, - rpcUrls: [url], - }, - ], - }); - } } - } else { - console.log('Metamask is already connected to the desired chain.'); } } catch (error) { console.error('Error checking and switching chain:', error); diff --git a/packages/commonwealth/client/scripts/controllers/app/webWallets/metamask_web_wallet.ts b/packages/commonwealth/client/scripts/controllers/app/webWallets/metamask_web_wallet.ts index 50c49b58031..5e6492df7d3 100644 --- a/packages/commonwealth/client/scripts/controllers/app/webWallets/metamask_web_wallet.ts +++ b/packages/commonwealth/client/scripts/controllers/app/webWallets/metamask_web_wallet.ts @@ -94,14 +94,14 @@ class MetamaskWebWalletController implements IWebWallet { } // ACTIONS - public async enable() { + public async enable(forceChainId?: string) { // TODO: use https://docs.metamask.io/guide/rpc-api.html#other-rpc-methods to switch active // chain according to currently active node, if one exists console.log('Attempting to enable Metamask'); this._enabling = true; try { // default to ETH - const chainId = this.getChainId(); + const chainId = forceChainId ?? this.getChainId(); // ensure we're on the correct chain @@ -209,43 +209,36 @@ class MetamaskWebWalletController implements IWebWallet { // TODO: chainChanged, disconnect events } - public async switchNetwork() { + public async switchNetwork(chainId?: string) { try { // Get current chain ID - const currentChainId = await this._web3.eth.getChainId(); - const communityChain = this.getChainId(); - const chainIdHex = `0x${parseInt(communityChain, 10).toString(16)}`; - if (currentChainId !== communityChain) { - try { - await window.ethereum.request({ - method: 'wallet_switchEthereumChain', - params: [{ chainId: `0x${chainIdHex}` }], + const communityChain = chainId ?? this.getChainId(); + const chainIdHex = parseInt(communityChain, 10).toString(16); + try { + await window.ethereum.request({ + method: 'wallet_switchEthereumChain', + params: [{ chainId: `0x${chainIdHex}` }], + }); + } catch (error) { + if (error.code === 4902) { + const chains = await $.getJSON('https://chainid.network/chains.json'); + const baseChain = chains.find((c) => c.chainId === communityChain); + // Check if the string contains '${' and '}' + const rpcUrl = baseChain.rpc.filter((r) => !/\${.*?}/.test(r)); + const url = + rpcUrl.length > 0 ? rpcUrl[0] : app.chain.meta.node.altWalletUrl; + await this._web3.givenProvider.request({ + method: 'wallet_addEthereumChain', + params: [ + { + chainId: chainIdHex, + chainName: baseChain.name, + nativeCurrency: baseChain.nativeCurrency, + rpcUrls: [url], + }, + ], }); - } catch (error) { - if (error.code === 4902) { - const chains = await $.getJSON( - 'https://chainid.network/chains.json', - ); - const baseChain = chains.find((c) => c.chainId === communityChain); - // Check if the string contains '${' and '}' - const rpcUrl = baseChain.rpc.filter((r) => !/\${.*?}/.test(r)); - const url = - rpcUrl.length > 0 ? rpcUrl[0] : app.chain.meta.node.altWalletUrl; - await this._web3.givenProvider.request({ - method: 'wallet_addEthereumChain', - params: [ - { - chainId: chainIdHex, - chainName: baseChain.name, - nativeCurrency: baseChain.nativeCurrency, - rpcUrls: [url], - }, - ], - }); - } } - } else { - console.log('Metamask is already connected to the desired chain.'); } } catch (error) { console.error('Error checking and switching chain:', error); diff --git a/packages/commonwealth/client/scripts/helpers/ContractHelpers/CommunityStakes.tsx b/packages/commonwealth/client/scripts/helpers/ContractHelpers/CommunityStakes.tsx index 748014bf8c6..ff40e6cda55 100644 --- a/packages/commonwealth/client/scripts/helpers/ContractHelpers/CommunityStakes.tsx +++ b/packages/commonwealth/client/scripts/helpers/ContractHelpers/CommunityStakes.tsx @@ -1,4 +1,3 @@ -import { String } from 'aws-sdk/clients/acm'; import { communityStakesAbi } from './Abi/CommunityStakesAbi'; import ContractBase from './ContractBase'; import NamespaceFactory from './NamespaceFactory'; @@ -111,6 +110,7 @@ class CommunityStakes extends ContractBase { if (!this.initialized || !this.walletEnabled) { await this.initialize(true); } + const namespaceAddress = await this.getNamespaceAddress(name); const totalPrice = await this.contract.methods .getBuyPriceAfterFee(namespaceAddress, id.toString(), amount.toString()) @@ -142,6 +142,7 @@ class CommunityStakes extends ContractBase { if (!this.initialized || !this.walletEnabled) { await this.initialize(true); } + const namespaceAddress = await this.getNamespaceAddress(name); let txReceipt; try { @@ -226,7 +227,7 @@ class CommunityStakes extends ContractBase { * @param walletAddress user wallet address * @returns string balance in ETH */ - async getUserEthBalance(walletAddress: String): Promise { + async getUserEthBalance(walletAddress: string): Promise { if (!this.initialized) { await this.initialize(); } diff --git a/packages/commonwealth/client/scripts/helpers/ContractHelpers/ContractBase.ts b/packages/commonwealth/client/scripts/helpers/ContractHelpers/ContractBase.ts index 7ea57b61079..18ba0e841db 100644 --- a/packages/commonwealth/client/scripts/helpers/ContractHelpers/ContractBase.ts +++ b/packages/commonwealth/client/scripts/helpers/ContractHelpers/ContractBase.ts @@ -20,7 +20,10 @@ abstract class ContractBase { this.rpc = rpc; } - async initialize(withWallet: boolean = false): Promise { + async initialize( + withWallet: boolean = false, + chainId?: string, + ): Promise { if (!this.initialized) { try { let provider = this.rpc; @@ -30,8 +33,9 @@ abstract class ContractBase { )[0]; if (!this.wallet.api) { - await this.wallet.enable(); + await this.wallet.enable(chainId); } + await this.wallet.switchNetwork(chainId); provider = this.wallet.api.givenProvider; this.walletEnabled = true; } diff --git a/packages/commonwealth/client/scripts/helpers/ContractHelpers/NamespaceFactory.ts b/packages/commonwealth/client/scripts/helpers/ContractHelpers/NamespaceFactory.ts index bd35ecd1c05..03ee19dcd9d 100644 --- a/packages/commonwealth/client/scripts/helpers/ContractHelpers/NamespaceFactory.ts +++ b/packages/commonwealth/client/scripts/helpers/ContractHelpers/NamespaceFactory.ts @@ -1,3 +1,4 @@ +import { String } from 'aws-sdk/clients/apigateway'; import { AbiItem } from 'web3-utils'; import { namespaceFactoryAbi } from './Abi/NamespaceFactoryAbi'; import { reservationHookAbi } from './Abi/ReservationHookAbi'; @@ -21,8 +22,11 @@ class NamespaceFactory extends ContractBase { * Initializes wallet and contracts. * This must be called after instantiation before other methods are available. */ - async initialize(withWallet: boolean = false): Promise { - await super.initialize(withWallet); + async initialize( + withWallet: boolean = false, + chainId?: string, + ): Promise { + await super.initialize(withWallet, chainId); const addr = await this.contract.methods.reservationHook().call(); if (addr.toLowerCase() !== '0x0000000000000000000000000000000000000000') { this.reservationHook = new this.web3.eth.Contract( @@ -81,9 +85,10 @@ class NamespaceFactory extends ContractBase { name: string, walletAddress: string, feeManager: string, + chainId: String, ): Promise { if (!this.initialized || !this.walletEnabled) { - await this.initialize(true); + await this.initialize(true, chainId); } // Check if name is available const namespaceStatus = await this.checkNamespaceReservation(name); @@ -115,10 +120,12 @@ class NamespaceFactory extends ContractBase { name: string, stakesId: number, walletAddress: string, + chainId: string, ): Promise { if (!this.initialized || !this.walletEnabled) { - await this.initialize(true); + await this.initialize(true, chainId); } + let txReceipt; try { txReceipt = await this.contract.methods diff --git a/packages/commonwealth/client/scripts/models/IWebWallet.ts b/packages/commonwealth/client/scripts/models/IWebWallet.ts index e022f346173..abe27e11fcf 100644 --- a/packages/commonwealth/client/scripts/models/IWebWallet.ts +++ b/packages/commonwealth/client/scripts/models/IWebWallet.ts @@ -12,7 +12,7 @@ interface IWebWallet { enabling: boolean; accounts: readonly AccountT[]; api?: any; - enable: () => Promise; + enable: (forceChainId: string) => Promise; reset?: () => Promise; getChainId(): string | null; @@ -24,6 +24,8 @@ interface IWebWallet { canvasSessionPayload: SessionPayload, ): Promise; + switchNetwork?(chainId?: string): Promise; + chain: ChainBase; defaultNetwork: ChainNetwork; diff --git a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/CreateCommunity.tsx b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/CreateCommunity.tsx index 59dc5516dc3..d0fda51399e 100644 --- a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/CreateCommunity.tsx +++ b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/CreateCommunity.tsx @@ -26,6 +26,7 @@ const CreateCommunity = () => { handleCompleteBasicInformationStep, onChangeStep, showCommunityStakeStep, + selectedChainId, } = useCreateCommunity(); useBrowserAnalyticsTrack({ @@ -64,6 +65,7 @@ const CreateCommunity = () => { createdCommunityName={createdCommunityName} createdCommunityId={createdCommunityId} selectedAddress={selectedAddress} + chainId={selectedChainId} /> ); diff --git a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityStakeStep/CommunityStakeStep.tsx b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityStakeStep/CommunityStakeStep.tsx index b26450b06dd..643de96f2f4 100644 --- a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityStakeStep/CommunityStakeStep.tsx +++ b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityStakeStep/CommunityStakeStep.tsx @@ -9,6 +9,7 @@ interface CommunityStakeStepProps { createdCommunityName: string; createdCommunityId: string; selectedAddress: AddressInfo; + chainId: string; } const CommunityStakeStep = ({ @@ -16,6 +17,7 @@ const CommunityStakeStep = ({ createdCommunityName, createdCommunityId, selectedAddress, + chainId, }: CommunityStakeStepProps) => { const [enableStakePage, setEnableStakePage] = useState(true); const [communityStakeData, setCommunityStakeData] = useState({ @@ -42,6 +44,7 @@ const CommunityStakeStep = ({ communityStakeData={communityStakeData} selectedAddress={selectedAddress} createdCommunityId={createdCommunityId} + chainId={chainId} /> )} diff --git a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityStakeStep/SignStakeTransactions/SignStakeTransactions.tsx b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityStakeStep/SignStakeTransactions/SignStakeTransactions.tsx index e72157a9069..bc3f4cb3a6b 100644 --- a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityStakeStep/SignStakeTransactions/SignStakeTransactions.tsx +++ b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityStakeStep/SignStakeTransactions/SignStakeTransactions.tsx @@ -20,6 +20,7 @@ const SignStakeTransactions = ({ communityStakeData, selectedAddress, createdCommunityId, + chainId, }: SignStakeTransactionsProps) => { const { handleReserveCommunityNamespace, reserveNamespaceData } = useReserveCommunityNamespace({ @@ -27,6 +28,7 @@ const SignStakeTransactions = ({ namespace: communityStakeData.namespace, symbol: communityStakeData.symbol, userAddress: selectedAddress.address, + chainId, }); const { handleLaunchCommunityStake, launchStakeData } = @@ -35,6 +37,7 @@ const SignStakeTransactions = ({ communityId: createdCommunityId, goToSuccessStep, selectedAddress: selectedAddress.address, + chainId, }); const isPreventLeaveEnabled = reserveNamespaceData.state !== 'not-started'; diff --git a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityStakeStep/SignStakeTransactions/useLaunchCommunityStake.tsx b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityStakeStep/SignStakeTransactions/useLaunchCommunityStake.tsx index b7e1844c5d4..32d5c204ae0 100644 --- a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityStakeStep/SignStakeTransactions/useLaunchCommunityStake.tsx +++ b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityStakeStep/SignStakeTransactions/useLaunchCommunityStake.tsx @@ -9,6 +9,7 @@ interface UseLaunchCommunityStakeProps { communityId: string; goToSuccessStep: () => void; selectedAddress: string; + chainId: string; } const useLaunchCommunityStake = ({ @@ -16,6 +17,7 @@ const useLaunchCommunityStake = ({ communityId, goToSuccessStep, selectedAddress, + chainId, }: UseLaunchCommunityStakeProps) => { const [launchStakeData, setLaunchStakeData] = useState(defaultActionState); @@ -34,6 +36,7 @@ const useLaunchCommunityStake = ({ namespace, commonProtocol.STAKE_ID, selectedAddress, + chainId, ); await updateCommunityStake({ diff --git a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityStakeStep/SignStakeTransactions/useReserveCommunityNamespace.tsx b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityStakeStep/SignStakeTransactions/useReserveCommunityNamespace.tsx index d1843f57907..54ea92764d6 100644 --- a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityStakeStep/SignStakeTransactions/useReserveCommunityNamespace.tsx +++ b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityStakeStep/SignStakeTransactions/useReserveCommunityNamespace.tsx @@ -9,6 +9,7 @@ interface UseReserveCommunityNamespaceProps { namespace: string; symbol: string; userAddress: string; + chainId: string; } const useReserveCommunityNamespace = ({ @@ -16,6 +17,7 @@ const useReserveCommunityNamespace = ({ namespace, symbol, userAddress, + chainId, }: UseReserveCommunityNamespaceProps) => { const [reserveNamespaceData, setReserveNamespaceData] = useState(defaultActionState); @@ -34,6 +36,7 @@ const useReserveCommunityNamespace = ({ namespace, userAddress, userAddress, + chainId, ); await updateCommunity({ diff --git a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityStakeStep/types.ts b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityStakeStep/types.ts index 0d335f34b42..c699cb1b10b 100644 --- a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityStakeStep/types.ts +++ b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/steps/CommunityStakeStep/types.ts @@ -16,6 +16,7 @@ export interface SignStakeTransactionsProps { communityStakeData: StakeData; selectedAddress: AddressInfo; createdCommunityId: string; + chainId: string; } export interface EnableStakeProps { diff --git a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/useCreateCommunity.ts b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/useCreateCommunity.ts index 6a91b7c8912..49ac6af6124 100644 --- a/packages/commonwealth/client/scripts/views/pages/CreateCommunity/useCreateCommunity.ts +++ b/packages/commonwealth/client/scripts/views/pages/CreateCommunity/useCreateCommunity.ts @@ -57,6 +57,7 @@ const useCreateCommunity = () => { handleCompleteBasicInformationStep, onChangeStep, showCommunityStakeStep, + selectedChainId, }; };