Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

Allow connecting Truffle Dashboard via WalletConnect #4926

Merged
merged 12 commits into from
Apr 3, 2022
Merged
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ packages/**/node_modules
node_modules
yarn-error.log
.vscode
.idea
.DS_Store

# truffle
Expand Down
24 changes: 8 additions & 16 deletions packages/dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,11 @@
"prepare": "yarn build",
"test": "jest"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"browserslist": [
">0.2%",
"not dead",
"not op_mini all"
],
"devDependencies": {
"@craco/craco": "^6.4.3",
"@testing-library/jest-dom": "^5.16.1",
Expand All @@ -65,15 +58,13 @@
"@types/react-dom": "^17.0.11",
"@types/web3": "^1.2.2",
"@types/ws": "^7.2.0",
"@web3-react/core": "^6.1.9",
"@web3-react/injected-connector": "^6.0.7",
"autoprefixer": "^9",
"axios": "^0.24.0",
"concurrently": "^6.5.1",
"cpy-cli": "^3.1.1",
"delay": "^5.0.0",
"ethereum-protocol": "^1.0.1",
"ethers": "^5.5.2",
"ethers": "^5.6.1",
"jest": "^27.4.5",
"postcss": "^8",
"react": "^17.0.2",
Expand All @@ -83,7 +74,8 @@
"tailwindcss": "npm:@tailwindcss/postcss7-compat",
"ts-jest": "^27.1.2",
"ts-node": "^10.4.0",
"typescript": "^4.1.4"
"typescript": "^4.1.4",
"wagmi": "^0.2.21"
},
"publishConfig": {
"access": "public"
Expand Down
52 changes: 48 additions & 4 deletions packages/dashboard/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,56 @@
import { getLibrary } from "./utils/utils";
import { Web3ReactProvider } from "@web3-react/core";
import Dashboard from "./Dashboard";

import { chain, Connector, defaultChains, Provider } from "wagmi";
import { InjectedConnector } from "wagmi/connectors/injected";
import { WalletConnectConnector } from "wagmi/connectors/walletConnect";

import { getDefaultProvider, providers as ethproviders } from "ethers";
import { getNetwork } from "@ethersproject/providers";

const defaultChain = chain.mainnet;

const getProvider = (_config: { chainId?: number; connector?: Connector }) => {
let wProvider = _config.connector?.getProvider(true);
console.debug("getProvider", {
wProvider,
winEth: window.ethereum,
_config,
INFURA_ID: process.env.REACT_APP_INFURA_ID
});
let ret: any;
if (!wProvider) {
ret = getDefaultProvider(getNetwork(_config.chainId ?? defaultChain.id));
} else {
wProvider
.enable()
.then((r: any) => console.debug(r))
.catch((e: any) => console.error(e));
ret = new ethproviders.Web3Provider(wProvider);
}
console.debug("getProvider.returning", {
wProvider,
winEth: window.ethereum,
ret
});
return ret;
};

const connectors = [
new InjectedConnector({ chains: defaultChains }),
new WalletConnectConnector({
chains: defaultChains,
options: {
infuraId: process.env.REACT_APP_INFURA_ID,
qrcode: true
}
})
];

function App() {
return (
<Web3ReactProvider getLibrary={getLibrary}>
<Provider connectors={connectors} provider={getProvider}>
<Dashboard />
</Web3ReactProvider>
</Provider>
);
}

Expand Down
40 changes: 28 additions & 12 deletions packages/dashboard/src/Dashboard.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,47 @@
import WebSocket from "isomorphic-ws";
import {
DashboardProviderMessage,
base64ToJson,
connectToMessageBusWithRetries,
DashboardProviderMessage,
isDashboardProviderMessage,
isInvalidateMessage,
isDebugMessage,
Message,
base64ToJson
isInvalidateMessage,
Message
} from "@truffle/dashboard-message-bus";
import { useWeb3React } from "@web3-react/core";
import WebSocket from "isomorphic-ws";
import { useEffect, useState } from "react";
import { useAccount, useConnect, useNetwork } from "wagmi";
import ConfirmNetworkChanged from "./components/ConfirmNetworkChange";
import { getPorts, respond } from "./utils/utils";
import Header from "./components/Header/Header";
import DashboardProvider from "./components/DashboardProvider/DashboardProvider";
import ConnectNetwork from "./components/ConnectNetwork";
import ConfirmNetworkChanged from "./components/ConfirmNetworkChange";

function Dashboard() {
const [paused, setPaused] = useState<boolean>(false);
const [connectedChainId, setConnectedChainId] = useState<number>();
const [connectedChainId, setConnectedChainId] = useState<
number | undefined
>();
const [chainId, setChainId] = useState<number>();
const [socket, setSocket] = useState<WebSocket | undefined>();
const [dashboardProviderRequests, setDashboardProviderRequests] = useState<
DashboardProviderMessage[]
>([]);

const { chainId } = useWeb3React();
const [{ data }] = useNetwork();
const [{}, disconnect] = useAccount();
const [{ data: connectData }] = useConnect();

useEffect(() => {
if (!chainId || !socket) return;
setChainId(data.chain?.id);

if (!chainId || !socket) return;
if (connectedChainId) {
if (connectedChainId !== chainId) setPaused(true);
if (connectedChainId === chainId) setPaused(false);
} else {
setConnectedChainId(chainId);
}
}, [chainId, connectedChainId, socket]);
}, [data, connectData, socket, chainId, connectedChainId]);

const initializeSocket = async () => {
if (socket && socket.readyState === WebSocket.OPEN) return;
Expand Down Expand Up @@ -80,9 +86,19 @@ function Dashboard() {
setSocket(connectedSocket);
};

const disconnectAccount = () => {
console.log("Disconnecting:");
// turn everything off.
disconnect();
setConnectedChainId(undefined);
setPaused(false);
socket?.close();
setSocket(undefined);
};

return (
<div className="h-full min-h-screen bg-gradient-to-b from-truffle-lighter to-truffle-light">
<Header />
<Header disconnect={disconnectAccount} />
{paused && chainId && connectedChainId && (
<ConfirmNetworkChanged
newChainId={chainId}
Expand Down
21 changes: 13 additions & 8 deletions packages/dashboard/src/components/ConnectNetwork.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,30 @@
import { useWeb3React } from "@web3-react/core";
import { providers } from "ethers";
import Card from "./common/Card";
import Button from "./common/Button";
import { InjectedConnector } from "@web3-react/injected-connector";
import NetworkIndicator from "./common/NetworkIndicator";
import { useConnect, useNetwork } from "wagmi";

interface Props {
confirm: () => void;
}

function ConnectNetwork({ confirm }: Props) {
const { chainId, activate } = useWeb3React<providers.Web3Provider>();
const injectedConnector = new InjectedConnector({});
const [{ data: connectData }, connect] = useConnect();
const [{ data: networkData }] = useNetwork();

const chainId = networkData.chain?.id;
const connectBody =
"Please connect your wallet to use the Truffle Dashboard Provider.";

const connectButton = (
<Button text="Connect Wallet" onClick={() => activate(injectedConnector)} />
<div>
{connectData.connectors.map(connector => (
<Button
key={connector.id}
onClick={() => connect(connector)}
text={connector.name}
/>
))}
</div>
);

const confirmBody = chainId && (
Expand All @@ -31,9 +38,7 @@ function ConnectNetwork({ confirm }: Props) {
</div>
</div>
);

const confirmButton = <Button text="Confirm" onClick={confirm} />;

return (
<div className="flex justify-center items-center py-20">
<div className="mx-3 w-3/4 max-w-4xl h-2/3 text-center">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import WebSocket from "isomorphic-ws";
import { useEffect } from "react";
import { useWeb3React } from "@web3-react/core";
import { providers } from "ethers";
import {
handleDashboardProviderRequest,
isInteractiveRequest,
Expand All @@ -11,6 +9,7 @@ import {
import Card from "../common/Card";
import IncomingRequest from "./IncomingRequest";
import type { DashboardProviderMessage } from "@truffle/dashboard-message-bus";
import { useConnect } from "wagmi";

interface Props {
paused: boolean;
Expand All @@ -24,7 +23,9 @@ interface Props {
}

function DashboardProvider({ paused, socket, requests, setRequests }: Props) {
const { account, library } = useWeb3React<providers.Web3Provider>();
const [{ data: connectData }] = useConnect();
const provider = connectData.connector?.getProvider();
const connector = connectData.connector;

useEffect(() => {
const removeFromRequests = (id: number) => {
Expand All @@ -33,7 +34,7 @@ function DashboardProvider({ paused, socket, requests, setRequests }: Props) {
);
};

if (!account || !library) return;
if (!connectData.connected || !provider) return;
if (paused) return;

// Automatically respond with an error for unsupported requests
Expand All @@ -49,20 +50,22 @@ function DashboardProvider({ paused, socket, requests, setRequests }: Props) {
!isInteractiveRequest(request) && !isUnsupportedRequest(request)
)
.forEach(request => {
handleDashboardProviderRequest(request, library.provider, socket);
handleDashboardProviderRequest(request, provider, connector, socket);
removeFromRequests(request.id);
});
}, [paused, requests, setRequests, socket, account, library]);
}, [paused, requests, setRequests, socket, connectData, provider, connector]);

const incomingRequests =
account && library && socket
connectData.connected && provider && socket
? requests
.filter(isInteractiveRequest)
.map(request => (
<IncomingRequest
key={request.id}
request={request}
setRequests={setRequests}
provider={library.provider}
provider={provider}
connector={connector}
socket={socket}
/>
))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,25 @@ interface Props {
| ((requests: DashboardProviderMessage[]) => DashboardProviderMessage[])
) => void;
provider: any;
connector: any;
socket: WebSocket;
}

function IncomingRequest({ provider, socket, request, setRequests }: Props) {
function IncomingRequest({
provider,
connector,
socket,
request,
setRequests
}: Props) {
const removeFromRequests = () => {
setRequests(previousRequests =>
previousRequests.filter(other => other.id !== request.id)
);
};

const process = async () => {
await handleDashboardProviderRequest(request, provider, socket);
await handleDashboardProviderRequest(request, provider, connector, socket);
removeFromRequests();
};

Expand Down
Loading