In this case, I would set the default provider as the RPC provider, then check to see if window.ethereum
exists. If it does exist, then we can try to use it as a provider and list accounts available to us. If the accounts array returns as empty, then we know there is no wallet connected to the site. Otherwise if the array returns one or more accounts, then set the signer and provider to MetaMask, overriding the original RPC provider.
Under the hood, this will call eth_accounts
via RPC. If no accounts are returned, then the user hasn't connected any of their metamask accounts to the site and thus none are available to use (I assume this is what you mean by "not logged in").
let provider = new ethers.providers.JsonRpcProvider("URL");
let signer;
if(window.ethereum) {
try {
const metaMaskProvider = new ethers.providers.Web3Provider(window.ethereum);
const accounts = await metaMaskProvider.listAccounts();
if (accounts.length) {
provider = metaMaskProvider;
signer = metaMaskProvider.getSigner();
}
} catch (exception) {
console.error('Unable to list accounts', exception);
}
}
let contract = new ethers.Contract(
contractAddress,
ABI,
signer ?? provider
);