One state machine
Treat every wallet action as a small state machine: idle, waiting for wallet, rejected, pending on-chain, confirmed, or failed.
Your UI should tell the user what is happening and what to do next. Never leave them guessing after they click a button.
Two pending states
There are two different waits. First, the wallet popup is waiting for the user to approve or reject. Second, the transaction hash is waiting to be included in a block.
MetaMask error code -32002 means a wallet request is already open. Do not send another request. Ask the user to open MetaMask and respond.