diff --git a/packages/admin-ui/src/common/types.ts b/packages/admin-ui/src/common/types.ts index 70ce85cd4..71b7ec60c 100644 --- a/packages/admin-ui/src/common/types.ts +++ b/packages/admin-ui/src/common/types.ts @@ -377,6 +377,7 @@ export interface ContainerLabelTypes { "dappnode.dnp.serviceName": string; "dappnode.dnp.instanceName": string; "dappnode.dnp.dependencies": Dependencies; + "dappnode.dnp.wallet": Wallet; "dappnode.dnp.avatar": string; "dappnode.dnp.origin": string; "dappnode.dnp.chain": ChainDriver; @@ -457,6 +458,7 @@ export interface PackageContainer { canBeFullnode?: boolean; isMain?: boolean; dockerTimeout?: number; + wallet?: Wallet; // Note: environment is only accessible doing a container inspect or reading the compose // envs?: PackageEnvs; } @@ -478,6 +480,7 @@ export type InstalledPackageData = Pick< | "chain" | "domainAlias" | "canBeFullnode" + | "wallet" > & { containers: PackageContainer[]; }; @@ -576,6 +579,19 @@ export interface DirectoryDnp { avatar?: string; } +export interface Wallet { + chainId: string; // A 0x-prefixed hexadecimal string + chainName: string; + nativeCurrency: { + name: string; + symbol: string; // 2-6 characters long + decimals: 18; + }; + rpcUrls: string[]; + blockExplorerUrls?: string[]; + iconUrls?: string[]; // Currently ignored. +} + export interface ChainData { dnpName: string; // "geth.dnp.dappnode.eth" name?: string; // Optional pretty name: "Geth" @@ -584,6 +600,7 @@ export interface ChainData { message: string; // "Blocks synced: 543000 / 654000" help?: string; // External link to show as help if needed: "http://geth.help" progress?: number; // 0.83027522935 + wallet?: Wallet; } export interface ProgressLog { diff --git a/packages/admin-ui/src/pages/dashboard/components/ChainCard.tsx b/packages/admin-ui/src/pages/dashboard/components/ChainCard.tsx index ccf53e157..a38d20c16 100644 --- a/packages/admin-ui/src/pages/dashboard/components/ChainCard.tsx +++ b/packages/admin-ui/src/pages/dashboard/components/ChainCard.tsx @@ -4,10 +4,12 @@ import ProgressBar from "react-bootstrap/ProgressBar"; import Card from "components/Card"; import RenderMarkdown from "components/RenderMarkdown"; import { prettyDnpName } from "utils/format"; -import { ChainData } from "types"; +import { ChainData, Wallet } from "types"; import { HelpTo } from "components/Help"; import { Link } from "react-router-dom"; import { rootPath as packagesRootPath } from "pages/packages"; +import Button from "components/Button"; +import { ethers } from "ethers"; export function ChainCards() { const chainData = useChainData(); @@ -22,7 +24,16 @@ export function ChainCards() { } function ChainCard(chain: ChainData) { - const { dnpName, name, message, help, progress, error, syncing } = chain; + const { + dnpName, + name, + message, + help, + progress, + error, + syncing, + wallet + } = chain; return (
@@ -41,7 +52,20 @@ function ChainCard(chain: ChainData) { ) : error ? ( ) : ( - + <> + + {wallet ? : null} + {dnpName === "nethermind-xdai.dnp.dappnode.eth" && ( + + )} + )}
@@ -53,3 +77,55 @@ function ChainCard(chain: ChainData) { ); } + +declare global { + interface Window { + ethereum: any; + } +} + +function ConnectWallet({ wallet }: { wallet: Wallet }) { + async function walletConnect() { + const provider = new ethers.providers.Web3Provider(window.ethereum); + console.log("provider: ", provider); + try { + console.log("trying.."); + + // https://eips.ethereum.org/EIPS/eip-3326 + await provider.send("wallet_switchEthereumChain", [ + { chainId: wallet.chainId } + ]); + console.log("failed"); + } catch (switchError) { + console.error(switchError); + // This error code indicates that the chain has not been added to MetaMask. + if (switchError.code === 4902) { + try { + // https://eips.ethereum.org/EIPS/eip-3085 + await provider.send( + "wallet_addEthereumChain", + // IMPORTANT! RPC without HTTPs is not allowed + // IMPORTANT! Add new chains with a default chain ID in metamask is not allowed family horn own sense negative orient tomorrow cheap recall mutual addict inmate + [ + { + chainId: wallet.chainId, + rpcUrls: [wallet.rpcUrls] + } + ] + ); + } catch (addError) { + // handle "add" error + throw addError; + } + } + // handle other "switch" errors + throw switchError; + } + } + + return ( + + ); +} diff --git a/packages/admin-ui/src/pages/dashboard/components/Dashboard.tsx b/packages/admin-ui/src/pages/dashboard/components/Dashboard.tsx index 1a3ca2101..d79d5e05e 100644 --- a/packages/admin-ui/src/pages/dashboard/components/Dashboard.tsx +++ b/packages/admin-ui/src/pages/dashboard/components/Dashboard.tsx @@ -7,7 +7,6 @@ import { PackageUpdates } from "./PackageUpdates"; // Components import SubTitle from "components/SubTitle"; import Title from "components/Title"; - import "./dashboard.scss"; export default function Dashboard() { diff --git a/packages/dappmanager/src/modules/chains/index.ts b/packages/dappmanager/src/modules/chains/index.ts index 5839d9f60..3eb07ad18 100644 --- a/packages/dappmanager/src/modules/chains/index.ts +++ b/packages/dappmanager/src/modules/chains/index.ts @@ -28,13 +28,13 @@ export async function getChainsData(): Promise { // Ethereum 2.0 multiservice should be handled in the driver if (dnp.containers.every(container => !container.running)) return; - const chainData = await runWithChainDriver(dnp, chainDriverName); + const chainDataResult = await runWithChainDriver(dnp, chainDriverName); loggedErrors.delete(dnp.dnpName); // Reset last seen error - if (chainData) + if (chainDataResult) chainsData.push({ dnpName: dnp.dnpName, - ...chainData + ...chainDataResult }); } catch (e) { // Only log chain errors the first time they are seen diff --git a/packages/dappmanager/src/modules/chains/types.ts b/packages/dappmanager/src/modules/chains/types.ts index c808e0a6a..d1d43aba6 100644 --- a/packages/dappmanager/src/modules/chains/types.ts +++ b/packages/dappmanager/src/modules/chains/types.ts @@ -7,4 +7,4 @@ export interface Chain { driverName: ChainDriver; // ethereum } -export type ChainDataResult = Omit; +export type ChainDataResult = Omit; diff --git a/packages/dappmanager/src/modules/compose/labelsDb.ts b/packages/dappmanager/src/modules/compose/labelsDb.ts index 20ebd381b..f9de13e91 100644 --- a/packages/dappmanager/src/modules/compose/labelsDb.ts +++ b/packages/dappmanager/src/modules/compose/labelsDb.ts @@ -46,6 +46,7 @@ const labelParseFns: { "dappnode.dnp.serviceName": parseString, "dappnode.dnp.instanceName": parseString, "dappnode.dnp.dependencies": value => parseJsonSafe(value) || {}, + "dappnode.dnp.wallet": value => parseJsonSafe(value), "dappnode.dnp.avatar": parseString, "dappnode.dnp.origin": parseString, "dappnode.dnp.chain": value => { @@ -80,6 +81,8 @@ const labelStringifyFns: { "dappnode.dnp.serviceName": writeString, "dappnode.dnp.instanceName": writeString, "dappnode.dnp.dependencies": writeJson, + "dappnode.dnp.wallet": value => + writeJson(value as unknown as Record), "dappnode.dnp.avatar": writeString, "dappnode.dnp.origin": writeString, "dappnode.dnp.chain": value =>