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: Handling of low funds cases in the UI (part-2) #568

Merged
merged 4 commits into from
Dec 11, 2024
Merged
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
2 changes: 0 additions & 2 deletions frontend/components/MainPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import { AddFundsSection } from './sections/AddFundsSection';
import { AlertSections } from './sections/AlertSections';
import { GasBalanceSection } from './sections/GasBalanceSection';
import { KeepAgentRunningSection } from './sections/KeepAgentRunningSection';
import { MainNeedsFunds } from './sections/NeedsFundsSection';
import { MainOlasBalance } from './sections/OlasBalanceSection';
import { RewardsSection } from './sections/RewardsSection';
import { StakingContractSection } from './sections/StakingContractUpdate';
Expand Down Expand Up @@ -78,7 +77,6 @@ export const Main = () => {
<KeepAgentRunningSection />
{isStakingContractSectionEnabled && <StakingContractSection />}
<GasBalanceSection />
<MainNeedsFunds />
<AddFundsSection />
</Flex>
</Card>
Expand Down
139 changes: 58 additions & 81 deletions frontend/components/MainPage/sections/AddFundsSection.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,5 @@
import {
CopyOutlined,
// QrcodeOutlined,
} from '@ant-design/icons';
import {
Button,
Flex,
message,
Popover,
// QRCode,
Tooltip,
Typography,
} from 'antd';
import { CopyOutlined } from '@ant-design/icons';
import { Button, Flex, message, Popover, Tooltip, Typography } from 'antd';
import Link from 'next/link';
import { forwardRef, useCallback, useMemo, useRef, useState } from 'react';
import styled from 'styled-components';
Expand All @@ -35,20 +24,6 @@ const CustomizedCardSection = styled(CardSection)<{ border?: boolean }>`
}
`;

const AddFundsGetTokensSection = () => {
const { selectedAgentConfig } = useServices();
const { evmHomeChainId: homeChainId } = selectedAgentConfig;

return (
<CardSection justify="center" bordertop="true" padding="16px 24px">
<Link target="_blank" href={SWAP_URL_BY_EVM_CHAIN[homeChainId]}>
Get OLAS + {CHAIN_CONFIG[homeChainId].nativeToken.symbol} on{' '}
{CHAIN_CONFIG[homeChainId].name} {UNICODE_SYMBOLS.EXTERNAL_LINK}
</Link>
</CardSection>
);
};

export const AddFundsSection = () => {
const fundSectionRef = useRef<HTMLDivElement>(null);
const [isAddFundsVisible, setIsAddFundsVisible] = useState(false);
Expand Down Expand Up @@ -88,47 +63,6 @@ export const AddFundsSection = () => {
);
};

/**
* Add funds section
*/
export const OpenAddFundsSection = forwardRef<HTMLDivElement>((_, ref) => {
const { selectedAgentConfig } = useServices();
const { evmHomeChainId: homeChainId } = selectedAgentConfig;
const { masterSafes } = useMasterWalletContext();
const masterSafeAddress = useMemo(
() =>
masterSafes?.find((wallet) => wallet.evmChainId === homeChainId)?.address,
[homeChainId, masterSafes],
);

const truncatedFundingAddress: string | undefined = useMemo(
() => masterSafeAddress && truncateAddress(masterSafeAddress, 4),
[masterSafeAddress],
);

const handleCopyAddress = useCallback(
() =>
masterSafeAddress &&
copyToClipboard(masterSafeAddress).then(() =>
message.success('Copied successfully!'),
),
[masterSafeAddress],
);

return (
<Flex vertical ref={ref}>
<AddFundsWarningAlertSection />
<AddFundsAddressSection
truncatedFundingAddress={truncatedFundingAddress}
fundingAddress={masterSafeAddress}
handleCopy={handleCopyAddress}
/>
<AddFundsGetTokensSection />
</Flex>
);
});
OpenAddFundsSection.displayName = 'OpenAddFundsSection';

const AddFundsWarningAlertSection = () => {
const { selectedAgentConfig } = useServices();
const { evmHomeChainId: homeChainId } = selectedAgentConfig;
Expand Down Expand Up @@ -166,25 +100,68 @@ const AddFundsAddressSection = ({
<Tooltip
title={
<span className="can-select-text flex">
{fundingAddress ?? 'Error loading address'}
{fundingAddress ?? 'Unable to load address'}
</span>
}
>
<Text title={fundingAddress}>{truncatedFundingAddress ?? NA}</Text>
</Tooltip>

<Button onClick={handleCopy} icon={<CopyOutlined />} size="large" />

{/* <Popover
title="Scan QR code"
content={
<QRCode
size={250}
value={`https://metamask.app.link/send/${fundingAddress}@${100}`}
/>
}
>
<Button icon={<QrcodeOutlined />} size="large" />
</Popover> */}
</CardSection>
);

const AddFundsGetTokensSection = () => {
const { selectedAgentConfig } = useServices();
const { evmHomeChainId: homeChainId } = selectedAgentConfig;

return (
<CardSection justify="center" bordertop="true" padding="16px 24px">
<Link target="_blank" href={SWAP_URL_BY_EVM_CHAIN[homeChainId]}>
Get OLAS + {CHAIN_CONFIG[homeChainId].nativeToken.symbol} on{' '}
{CHAIN_CONFIG[homeChainId].name} {UNICODE_SYMBOLS.EXTERNAL_LINK}
</Link>
</CardSection>
);
};

/**
* Add funds section
*/
export const OpenAddFundsSection = forwardRef<HTMLDivElement>((_, ref) => {
const { selectedAgentConfig } = useServices();
const { evmHomeChainId: homeChainId } = selectedAgentConfig;
const { masterSafes } = useMasterWalletContext();
const masterSafeAddress = useMemo(
() =>
masterSafes?.find((wallet) => wallet.evmChainId === homeChainId)?.address,
[homeChainId, masterSafes],
);

const truncatedFundingAddress: string | undefined = useMemo(
() => masterSafeAddress && truncateAddress(masterSafeAddress, 4),
[masterSafeAddress],
);

const handleCopyAddress = useCallback(
() =>
masterSafeAddress &&
copyToClipboard(masterSafeAddress).then(() =>
message.success('Copied successfully!'),
),
[masterSafeAddress],
);

return (
<Flex vertical ref={ref}>
<AddFundsWarningAlertSection />
<AddFundsAddressSection
truncatedFundingAddress={truncatedFundingAddress}
fundingAddress={masterSafeAddress}
handleCopy={handleCopyAddress}
/>
<AddFundsGetTokensSection />
</Flex>
);
});
OpenAddFundsSection.displayName = 'OpenAddFundsSection';
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { LowOperatingBalanceAlert } from './LowOperatingBalanceAlert';
import { LowSafeSignerBalanceAlert } from './LowSafeSignerBalanceAlert';
import { MainNeedsFunds } from './MainNeedsFunds';

export const LowFunds = () => (
<>
<MainNeedsFunds />
<LowOperatingBalanceAlert />
<LowSafeSignerBalanceAlert />
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,19 @@ import { useMemo } from 'react';
import { CustomAlert } from '@/components/Alert';
import { LOW_MASTER_SAFE_BALANCE } from '@/constants/thresholds';
import { useMasterBalances } from '@/hooks/useBalanceContext';
import { useChainDetails } from '@/hooks/useChainDetails';
import { useServices } from '@/hooks/useServices';
import { useStore } from '@/hooks/useStore';
import { useMasterWalletContext } from '@/hooks/useWallet';

import { InlineBanner } from './InlineBanner';
import { useLowFundsDetails } from './useLowFunds';

const { Text, Title } = Typography;

export const LowOperatingBalanceAlert = () => {
const { storeState } = useStore();
const { selectedAgentConfig } = useServices();
const { masterSafes } = useMasterWalletContext();
const { isLoaded: isBalanceLoaded, masterSafeNativeGasBalance } =
useMasterBalances();

const homeChainId = selectedAgentConfig.evmHomeChainId;
const { name, symbol } = useChainDetails(homeChainId);

const selectedMasterSafe = useMemo(() => {
if (!masterSafes) return;
if (!homeChainId) return;

return masterSafes.find(
(masterSafe) => masterSafe.evmChainId === homeChainId,
);
}, [masterSafes, homeChainId]);
const { chainName, tokenSymbol, masterSafeAddress } = useLowFundsDetails();

const isLowBalance = useMemo(() => {
if (!masterSafeNativeGasBalance) return false;
Expand All @@ -53,18 +39,18 @@ export const LowOperatingBalanceAlert = () => {
</Title>
<Text>
To run your agent, add at least
<Text strong>{` ${LOW_MASTER_SAFE_BALANCE} ${symbol} `}</Text>
on {name} chain to your safe.
<Text strong>{` ${LOW_MASTER_SAFE_BALANCE} ${tokenSymbol} `}</Text>
on {chainName} chain to your safe.
</Text>
<Text>
Your agent is at risk of missing its targets, which would result in
several days&apos; suspension.
</Text>

{selectedMasterSafe?.address && (
{masterSafeAddress && (
<InlineBanner
text="Your safe address"
address={selectedMasterSafe.address}
address={masterSafeAddress}
/>
)}
</Flex>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,15 @@ import { useMemo } from 'react';
import { CustomAlert } from '@/components/Alert';
import { LOW_AGENT_SAFE_BALANCE } from '@/constants/thresholds';
import { useMasterBalances } from '@/hooks/useBalanceContext';
import { useChainDetails } from '@/hooks/useChainDetails';
import { useServices } from '@/hooks/useServices';
import { useStore } from '@/hooks/useStore';
import { useMasterWalletContext } from '@/hooks/useWallet';

import { InlineBanner } from './InlineBanner';
import { useLowFundsDetails } from './useLowFunds';

const { Text, Title } = Typography;

export const LowSafeSignerBalanceAlert = () => {
const { storeState } = useStore();
const { selectedAgentConfig } = useServices();
const { masterEoa } = useMasterWalletContext();
const { isLoaded: isBalanceLoaded, masterEoaNativeGasBalance } =
useMasterBalances();

Expand All @@ -25,8 +21,7 @@ export const LowSafeSignerBalanceAlert = () => {
return masterEoaNativeGasBalance < LOW_AGENT_SAFE_BALANCE;
}, [masterEoaNativeGasBalance]);

const homeChainId = selectedAgentConfig.evmHomeChainId;
const { name, symbol } = useChainDetails(homeChainId);
const { chainName, tokenSymbol, masterEoaAddress } = useLowFundsDetails();

if (!isBalanceLoaded) return null;
if (!storeState?.isInitialFunded) return;
Expand All @@ -44,18 +39,18 @@ export const LowSafeSignerBalanceAlert = () => {
</Title>
<Text>
To keep your agent operational, add
<Text strong>{` ${LOW_AGENT_SAFE_BALANCE} ${symbol} `}</Text>
on {name} chain to the safe signer.
<Text strong>{` ${LOW_AGENT_SAFE_BALANCE} ${tokenSymbol} `}</Text>
on {chainName} chain to the safe signer.
</Text>
<Text>
Your agent is at risk of missing its targets, which would result in
several days&apos; suspension.
</Text>

{masterEoa?.address && (
{masterEoaAddress && (
<InlineBanner
text="Safe signer address"
address={masterEoa.address}
address={masterEoaAddress}
/>
)}
</Flex>
Expand Down
Loading
Loading