How do I connect Wagmi with Trust Wallet, so that users can connect their Trust Wallet accounts with my dApp? The Trust Wallet connector is not included in the official Wagmi connectors base, so I attempted to do it with the following code:
App.jsx
import { WagmiConfig, configureChains, createConfig } from "wagmi";
import { WalletConnectConnector } from "wagmi/connectors/walletConnect";
import { MetaMaskConnector } from "wagmi/connectors/metaMask";
import { InjectedConnector } from "wagmi/connectors/injected";
import { goerli } from "wagmi/chains";
import { publicProvider } from "wagmi/providers/public";
import ConnectAccount from "./ConnectAccount";
const { chains, publicClient, webSocketPublicClient } = configureChains(
[goerli],
[publicProvider()]
);
export const metamaskConnector = new MetaMaskConnector({
chains,
options: {
UNSTABLE_shimOnConnectSelectAccount: true,
shimDisconnect: true
}
});
export const walletConnectConnector = new WalletConnectConnector({
chains,
options: {
projectId: "2a42e5f44eaac002e60ba61a895028f6",
metadata: {
name: "Seedify",
description: "Seedworld is a UGC based Gaming Metaverse.",
url: document.URL,
icons: ["https://seedworld.io/favicon.ico"]
}
}
});
export const trustWalletConnector = new InjectedConnector({
chains,
options: {
name: "trustwallet",
shimDisconnect: true,
getProvider: () =>
typeof window !== "undefined" ? window.trustwallet : undefined
}
});
/*new TrustWalletConnector({
chains,
});*/
const config = createConfig({
publicClient,
webSocketPublicClient,
connectors: [trustWalletConnector, metamaskConnector]
});
export default function App() {
return (
<WagmiConfig config={config}>
<div className="App">
<ConnectAccount />
</div>
</WagmiConfig>
);
}
ConnectWalletButton.jsx
import { useAccount, useConnect } from "wagmi";
import { metamaskConnector, trustWalletConnector } from "./App";
export default function ConnectAccount() {
const { isLoading, address, isConnected } = useAccount();
const { connect } = useConnect();
return (
<>
<button
onClick={() => {
connect({
connector: trustWalletConnector
});
}}
>
{isLoading ? "Is loading..." : "Connect your Trust Wallet"}
</button>
<button
onClick={() => {
connect({
connector: metamaskConnector
});
}}
>
{isLoading ? "Is loading..." : "Connect your Metamask Wallet"}
</button>
{isConnected ? <span>{address}</span> : <></>}
</>
);
}
I get no prompt when clicking on the "Connect with Trust Wallet" button, it's just stuck at 'Loading...' forever.
Please see this minimal reproducible example on Codesandbox: https://codesandbox.io/s/strange-morning-lmml82?file=/src/ConnectAccount.js
Please help me with any advice!
What would be the best way to integrate Trust Wallet provider and Wagmi/Viem?
I figured out Wagmi doesn't work nicely with TrustWallet on its own.
So I had to write some custom connector hooks to make it work:
hooks/useConnectCustom.tsx
import React from "react";
import { useConnect } from "wagmi";
import { trustWalletConnector, metamaskConnector, walletConnectConnector } from "../wagmi";
type ConnectorName = 'metamask' | 'wc' | 'trust';
interface UseConnectProps {
onConnect: () => void;
}
export const useConnectCustom = ({
onConnect
}: UseConnectProps): {
isLoading: boolean;
connect: (connectorName: ConnectorName) => void;
isTWConnecting: boolean;
} => {
const {pendingConnector, connect : connectMetamask, isLoading: isMetamaskLoading} = useConnect({
connector: metamaskConnector
});
const {connect : connectWalletConnect, isLoading: isWalletConnectLoading} = useConnect({
connector: walletConnectConnector
});
const {connect : connectTrustWallet, isLoading: isTrustWalletLoading} = useConnect({
connector: trustWalletConnector
});
const connect = (connectorName: ConnectorName) => {
switch(connectorName) {
case 'metamask':
connectMetamask();
break;
case 'wc':
connectWalletConnect();
break;
case 'trust':
onConnect();
connectTrustWallet()
break;
}
}
return {
connect,
isTWConnecting: pendingConnector === trustWalletConnector,
isLoading: isMetamaskLoading || isWalletConnectLoading
}
}
hooks/useAccountCustom.tsx
import React, { useEffect, useState } from "react";
import { Address, useAccount, useDisconnect } from "wagmi";
import { isAddress } from "viem";
import useLocalStorage from "use-local-storage";
export const useAccountCustom = (): {
address: Address | undefined;
isConnected: boolean;
onConnect: () => void;
disconnect: () => void;
isConnecting: boolean;
} => {
const { address: wagmiAddress } = useAccount();
const { disconnect } = useDisconnect();
const [isDisconnected, setIsDisconnected] = useLocalStorage<boolean>('is-tw-disconnected', false);
const [trustWalletAddress, setTrustWalletAddress] = useState<Address | undefined>();
useEffect(() => {
setInterval(() => {
window.trustwallet.request({method:'eth_accounts'}).then((res: string[]) => {
isAddress(res[0]) && setTrustWalletAddress(res[0]);
})
}, 1000);
}, []);
return {
isConnecting: false,
address: wagmiAddress || (!isDisconnected ? trustWalletAddress : undefined),
isConnected: !!(wagmiAddress || (!isDisconnected && trustWalletAddress)),
onConnect: () => {
setIsDisconnected(false);
},
disconnect: () => {
disconnect();
setIsDisconnected(true);
}
};
};
As can be seen from the code above, I'm refetching the value of TrustWallet when the first time the request has already been fulfilled (by a call from Wagmi).
useEffect(() => {
setInterval(() => {
window.trustwallet.request({method:'eth_accounts'}).then((res: string[]) => {
isAddress(res[0]) && setTrustWalletAddress(res[0]);
})
}, 1000);
}, []);
This config works for me to make TrustWallet, Metamask and WalletConnect all work with Wagmi/Viem, I'm not sure how useContractWrite()
will work with that config though.
On its own, multiple InjectedConnectors
can be buggy because of EIP-6963.