Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add the possibility to read the chain without connected wallet #45

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 49 additions & 111 deletions soroban-react-dapp/src/components/web3/ChainInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,116 +1,54 @@
import { Card, Link } from '@chakra-ui/react'
import { useSorobanReact } from '@soroban-react/core'
import { type FC, useEffect, useState } from 'react'
import { HiOutlineExternalLink } from 'react-icons/hi'
import 'twin.macro'
import React, { useEffect, useState } from 'react';
import { Card, Link } from '@chakra-ui/react';
import { useSorobanReact } from '@soroban-react/core';
import 'twin.macro';

interface ChainInfo {
Chain: string | undefined,
PassPhrase: string,
NetworkURL: string,
sorobanURL: string | undefined
}
export const ChainInfo: FC = () => {
const sorobanContext = useSorobanReact();
// const { api, activeChain } =
const [chainInfo, setChainInfo] = useState<ChainInfo>()

// Fetch Chain Info
const fetchChainInfo = () => {
// if (!api) {
// setChainInfo(undefined)
// return
// }

const chain = sorobanContext.activeChain ?? {name:"", networkPassphrase:"",networkUrl:"",sorobanRpcUrl:""}
// const version = (await api.rpc.system.version())?.toString() || ''
// const properties = ((await api.rpc.system.properties())?.toHuman() as any) || {}
// const tokenSymbol = properties?.tokenSymbol?.[0] || 'UNIT'
// const tokenDecimals = properties?.tokenDecimals?.[0] || 12
const chainInfo = {
Chain: chain.name,
PassPhrase: chain.networkPassphrase,
NetworkURL: chain.networkUrl,
sorobanURL: chain.sorobanRpcUrl
// Token: `${tokenSymbol} (${tokenDecimals} Decimals)`,
}
setChainInfo(chainInfo)
}
useEffect(fetchChainInfo, [sorobanContext])
Chain: string | undefined;
PassPhrase: string;
NetworkURL: string;
sorobanURL: string | undefined;
}

// Connection Loading Indicator
// if (!api)
// return (
// <div tw="mt-8 mb-4 flex flex-col items-center justify-center space-y-3 text-center font-mono text-sm text-gray-400 sm:(flex-row space-x-3 space-y-0)">
// <Spinner size="sm" />
// <div>
// Connecting to {activeChain?.name} ({activeChain?.rpcUrls?.[0]})
// </div>
// </div>
// )
export const ChainInfo: React.FC = () => {
const sorobanContext = useSorobanReact();
const [chainInfo, setChainInfo] = useState<ChainInfo>();

useEffect(() => {
const fetchChainInfo = () => {
const chain = sorobanContext.activeChain ?? { name: "", networkPassphrase: "", networkUrl: "", sorobanRpcUrl: "" };
const chainInfo = {
Chain: chain.name,
PassPhrase: chain.networkPassphrase,
NetworkURL: chain.networkUrl,
sorobanURL: chain.sorobanRpcUrl,
};
setChainInfo(chainInfo);
};

fetchChainInfo();
}, [sorobanContext.activeChain]);

return (
<>
<div tw="flex grow flex-col space-y-4 max-w-[20rem]">
<h2 tw="text-center font-mono text-gray-400">Chain Info</h2>

<Card variant="outline" p={4} bgColor="whiteAlpha.100">
{/* Metadata */}
{Object.entries(chainInfo ?? {}).map(([key, value]:[string, string]) => (
<div key={key} tw="text-sm leading-7">
{key}:
<strong tw="float-right ml-6 truncate max-w-[15rem]" title={value}>
{value}
</strong>
</div>
))}

{/* <div tw="mt-3 flex items-center justify-center space-x-3"> */}
{/* Explorer Link */}
{
<Link
href={"https://stellar.expert/explorer/testnet/"}
target="_blank"
tw="flex items-center justify-center gap-1 text-center text-sm text-gray-400 hover:text-white"
>
TestNet Explorer <HiOutlineExternalLink />
</Link>
}
{/* Faucet Link */}
{/* {!!activeChain?.faucetUrls?.length && (
<Link
href={activeChain.faucetUrls[0]}
target="_blank"
tw="flex items-center justify-center gap-1 text-center text-sm text-gray-400 hover:text-white"
>
Faucet <HiOutlineExternalLink />
</Link>
)} */}
{/* Contracts UI Link */}
{/* {!!activeChain?.rpcUrls?.length && (
<Link
href={`https://contracts-ui.substrate.io/?rpc=${activeChain.rpcUrls[0]}`}
target="_blank"
tw="flex items-center justify-center gap-1 text-center text-sm text-gray-400 hover:text-white"
>
Contracts UI <HiOutlineExternalLink />
</Link>
)} */}
{/* </div> */}
</Card>

{/* Mainnet Security Disclaimer */}
{/* {!activeChain?.testnet && (
<>
<h2 tw="text-center font-mono text-red-400">Security Disclaimer</h2>

<Card variant="outline" p={4} bgColor="red.500" borderColor="red.300" fontSize={'sm'}>
You are interacting with un-audited mainnet contracts and risk all your funds. Never
transfer tokens to this contract.
</Card>
</>
)} */}
</div>
</>
)
}
<div tw="flex grow flex-col space-y-4 max-w-[20rem]">
<h2 tw="text-center font-mono text-gray-400">Chain Info</h2>
<Card variant="outline" p={4} bgColor="whiteAlpha.100">
{Object.entries(chainInfo ?? {}).map(([key, value]: [string, string]) => (
<div key={key} tw="text-sm leading-7">
{key}:
<strong tw="float-right ml-6 truncate max-w-[15rem]" title={value}>
{value}
</strong>
</div>
))}
<Link
href={"https://stellar.expert/explorer/testnet/"}
target="_blank"
tw="flex items-center justify-center gap-1 text-center text-sm text-gray-400 hover:text-white"
>
TestNet Explorer
</Link>
</Card>
</div>
);
};
170 changes: 36 additions & 134 deletions soroban-react-dapp/src/components/web3/ConnectButton.tsx
Original file line number Diff line number Diff line change
@@ -1,138 +1,40 @@
import 'twin.macro'
import {useSorobanReact} from "@soroban-react/core"

import {
Button,
HStack,
Menu,
MenuButton,
MenuDivider,
MenuItem,
MenuList,
Text,
VStack,
} from '@chakra-ui/react'
import { FiChevronDown } from 'react-icons/fi'
import { AiOutlineCheckCircle, AiOutlineDisconnect } from 'react-icons/ai'
import toast from 'react-hot-toast'
import type { WalletChain } from '@soroban-react/types'

export const ConnectButton = () => {
// Connect Button
const sorobanContext = useSorobanReact()

const {activeChain, address, disconnect, setActiveConnectorAndConnect, setActiveChain} = sorobanContext;
const activeAccount = address;

const browserWallets = sorobanContext.connectors;
const supportedChains = sorobanContext.chains;

const handleContractInteraction = (chain: WalletChain) => {
if (!chain.name || chain.name.toLowerCase() === 'standalone') {
toast.error('Please deploy the contract before proceeding when using the standalone chain..');
} else {
setActiveChain && setActiveChain(chain);
toast.success(`Active chain changed to ${chain.name}`);
import React from 'react';
import { Button, Spinner } from '@chakra-ui/react';
import { useSorobanReact } from '@soroban-react/core';
import 'twin.macro';

interface ConnectButtonProps {
network: string;
}

export const ConnectButton: React.FC<ConnectButtonProps> = ({ network }) => {
const { address, connect, disconnect, isLoading } = useSorobanReact();

const handleConnect = async () => {
try {
await connect();
} catch (error) {
console.error('Failed to connect wallet', error);
}
};

if (!activeAccount)
return (
<Menu>
<MenuButton
as={Button}
// isLoading={isConnecting}
size="md"
rightIcon={<FiChevronDown size={22} />}
py={6}
fontWeight="bold"
rounded="2xl"
colorScheme="purple"
>
Connect Wallet
</MenuButton>

<MenuList bgColor="blackAlpha.900" borderColor="whiteAlpha.300" rounded="2xl">
{/* Installed Wallets */}
{!activeAccount &&
browserWallets.map((w) =>
<MenuItem
key={w.name}
onClick={() => {
setActiveConnectorAndConnect && setActiveConnectorAndConnect(w)
}}
tw="bg-transparent hocus:bg-gray-800"
>
{w.name}
</MenuItem>
)}
</MenuList>
</Menu>
)


// Account Menu & Disconnect Button
return (
<Menu matchWidth>
<HStack>
{/* Account Name, Address, and AZNS-Domain (if assigned) */}
<MenuButton
as={Button}
rightIcon={<FiChevronDown size={22} />}
hidden={false}
py={6}
pl={5}
rounded="2xl"
fontWeight="bold"
>
<VStack spacing={0.5}>
{/* <AccountName account={activeAccount} /> */}
<Text>{activeChain?.name}</Text>
<Text fontSize="xs" fontWeight="normal" opacity={0.75}>
{address}
</Text>
</VStack>
</MenuButton>
</HStack>

<MenuList
bgColor="blackAlpha.900"
borderColor="whiteAlpha.300"
rounded="2xl"
maxHeight="40vh"
>
{/* Supported Chains */}
{/* Commented this as changing chain with the setActiveChain from soroban-react
is not working well - should change chain in the browser extension */}
{/* {supportedChains.map((chain) => (
<MenuItem
key={chain.name}
// isDisabled={chain.network === activeChain?.network}
onClick={() => {
// toast.error(`Not implemented yet. Please switch chain via the wallet extension.`)
handleContractInteraction(chain)
}}
tw="bg-transparent hocus:bg-gray-800"
>
<VStack align="start" spacing={0}>
<HStack>
<Text>{chain.name}</Text>
{chain.network === activeChain?.network && <AiOutlineCheckCircle size={16} />}
</HStack>
</VStack>
</MenuItem>
))} */}
const handleDisconnect = async () => {
try {
await disconnect();
} catch (error) {
console.error('Failed to disconnect wallet', error);
}
};

{/* Disconnect Button */}
<MenuDivider />
<MenuItem
onClick={async () => {console.log("Disconnecting"); await disconnect()}}
icon={<AiOutlineDisconnect size={18} />}
tw="bg-transparent hocus:bg-gray-800"
>
Disconnect
</MenuItem>
</MenuList>
</Menu>
)
}
return (
<Button
onClick={address ? handleDisconnect : handleConnect}
isLoading={isLoading}
colorScheme={address ? 'red' : 'blue'}
tw="mt-4"
>
{address ? `Disconnect (${address.slice(0, 6)}...${address.slice(-4)})` : 'Connect Wallet'}
{isLoading && <Spinner size="sm" tw="ml-2" />}
</Button>
);
};
Loading