WalletConnect - can you maintain state across invocations

54 Views Asked by At

I use https://docs.walletconnect.com/web3modal/about in an Astro.build Starlight web site:

I wish to provide Web3 auth and use Web3Modal.

It works as expected EXCEPT astro does not maintain any client-side Javascript state so the Web3Modal instance is recreated on each new page. And this brings up the 'connect to wallet' modal each time. It's not the full 'connect to wallet' and the connection state is obviously known:

enter image description here

I've been discussing it with the Astro people and I might have a work-around for the full site refresh issue, but I'm not relying on it. But more than that I'd generally like to know ...

Is there way to maintain WalletConnect state for Web3Modal so subsequent connections will just return that state (ie. isConnected) and not the 'wallet information' modal shown above? Or is there something I can inspect to know not to run modal.open()? I've had a look and modal.getAddress() is undefined until after that modal appears.

I see for example on https://docs.walletconnect.com/api/auth/dapp-usage that the authClient.request returns a URI.

import AuthClient, { generateNonce } from '@walletconnect/auth-client'

// ...

const { uri } = await authClient.request({
  aud: '<FULL_URL_OF_LOGIN_PAGE>',
  domain: '<YOUR_DOMAIN>',
  chainId: 'eip155:1',
  type: 'eip4361',
  nonce: generateNonce()
})

Could Web3Modal do something similar where that uri is a link back in to the state?

Here is my code if that helps. I'm using the vanilla JS / Web code.

// file: myWalletConnect - Singleton but that isn't a singleton as full refresh happening
export default class Modal2 {
    modal: Web3Modal;

    constructor() {
        if (this.constructor.instance) {
            return this.constructor.instance;
        }
        this.constructor.instance = this;
        this.modal = this.create();
    }

    private create(): Web3Modal {
        console.log(`create new Modal`)
        const projectId = 'abc'
        const GOERLI_RPC_URL = "https://eth-goerli.g.alchemy.com/v2/xyz"

        const mainnet = {
            chainId: 1,
            name: 'Ethereum',
            currency: 'ETH',
            explorerUrl: 'https://etherscan.io',
            rpcUrl: 'https://cloudflare-eth.com'
        }

        const goerli = {
            chainId: 5,
            name: 'GEthereum',
            currency: 'ETH',
            explorerUrl: 'https://goerli.etherscan.io/',
            rpcUrl: GOERLI_RPC_URL
        }

        const metadata = {
            name: 'Band TShirts documentation',
            description: 'Dev and user documentation for Band TShirts app',
            url: 'https://example.com',
            icons: ['https://example.com/icon']
        }

        const modal: Web3Modal = createWeb3Modal({
            ethersConfig: defaultConfig({metadata}),
            chains: [goerli, mainnet],
            projectId
        })
        return modal;
    }
}

And this is what is rendered:

// file: WalletComponent.astro (essentially this is JS/TS )
<div id="walletDetails">
    <span class="wallet-label">Wallet:</span>
    <!--Show one or the other of these-->
    <button id="open-connect-modal">Open Modal</button>
    <span class="walletDetails-address"></span>
</div>

<script>
    import Modal2 from "../myWalletConnect";

    const modal = new Modal().modal;

    const openConnectModelId = 'open-connect-modal';
    const walletDetailsAddressClass = 'walletDetails-address';

    const openConnectModalBtn = document.querySelector(`#${openConnectModelId}`)
    openConnectModalBtn.addEventListener('click', () => openConnect());

    const manageUIState = () => {
        // update state based on modal.getAddress() and other fields
    }

    const openConnect = async () => {

        function handleChange({provider, providerType, address, chainId, error, isConnected}) {
            manageUIState(); // draw the UI
        }

        if (!modal.getIsConnected()) {
            console.log(`Wallet - open modal`);
            await modal.open()
            manageUIState();
            modal.subscribeProvider(handleChange)
        }

    }

    openConnect();
</script>
0

There are 0 best solutions below