Skip to content

Commit

Permalink
feat: add MainNeedsFunds component to display funding requirements an…
Browse files Browse the repository at this point in the history
…d integrate with low funds alert
  • Loading branch information
mohandast52 committed Dec 11, 2024
1 parent ead9d08 commit 7cb42a7
Show file tree
Hide file tree
Showing 7 changed files with 201 additions and 157 deletions.
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
112 changes: 56 additions & 56 deletions frontend/components/MainPage/sections/AddFundsSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,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 @@ -77,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 @@ -155,7 +100,7 @@ const AddFundsAddressSection = ({
<Tooltip
title={
<span className="can-select-text flex">
{fundingAddress ?? 'Error loading address'}
{fundingAddress ?? 'Unable to load address'}
</span>
}
>
Expand All @@ -165,3 +110,58 @@ const AddFundsAddressSection = ({
<Button onClick={handleCopy} icon={<CopyOutlined />} size="large" />
</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
@@ -0,0 +1,111 @@
import { Flex, Typography } from 'antd';
import { useEffect, useMemo } from 'react';

import { CustomAlert } from '@/components/Alert';
import { getNativeTokenSymbol } from '@/config/tokens';
import { UNICODE_SYMBOLS } from '@/constants/symbols';
import { TokenSymbol } from '@/enums/Token';
import { useElectronApi } from '@/hooks/useElectronApi';
import { useNeedsFunds } from '@/hooks/useNeedsFunds';
import { useServices } from '@/hooks/useServices';
import { useStakingProgram } from '@/hooks/useStakingProgram';

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

const { Text, Title } = Typography;

export const MainNeedsFunds = () => {
const { selectedStakingProgramId } = useStakingProgram();

const {
hasEnoughEthForInitialFunding,
hasEnoughOlasForInitialFunding,
serviceFundRequirements,
isInitialFunded,
needsInitialFunding,
} = useNeedsFunds(selectedStakingProgramId);

const { selectedAgentConfig } = useServices();
const { evmHomeChainId: homeChainId } = selectedAgentConfig;
const nativeTokenSymbol = getNativeTokenSymbol(homeChainId);
const { chainName, masterSafeAddress } = useLowFundsDetails();

const electronApi = useElectronApi();

useEffect(() => {
if (
hasEnoughEthForInitialFunding &&
hasEnoughOlasForInitialFunding &&
!isInitialFunded
) {
electronApi.store?.set?.('isInitialFunded', true);
}
}, [
electronApi.store,
hasEnoughEthForInitialFunding,
hasEnoughOlasForInitialFunding,
isInitialFunded,
]);

const olasRequired = useMemo(() => {
if (hasEnoughOlasForInitialFunding) return null;
const olas = serviceFundRequirements[homeChainId][TokenSymbol.OLAS];
return `${UNICODE_SYMBOLS.OLAS}${olas} OLAS `;
}, [homeChainId, hasEnoughOlasForInitialFunding, serviceFundRequirements]);

const nativeTokenRequired = useMemo(() => {
if (hasEnoughEthForInitialFunding) return null;
const native = serviceFundRequirements[homeChainId][nativeTokenSymbol];
return `${native} ${nativeTokenSymbol}`;
}, [
homeChainId,
hasEnoughEthForInitialFunding,
serviceFundRequirements,
nativeTokenSymbol,
]);

if (!needsInitialFunding) return null;

return (
<CustomAlert
fullWidth
showIcon
message={
<Flex vertical gap={8} align="flex-start">
<Title level={5} style={{ margin: 0 }}>
Fund your agent
</Title>

<Text>
To activate your agent, add these amounts on {chainName} chain to
your safe:
</Text>

<Flex gap={0} vertical>
{!hasEnoughOlasForInitialFunding && (
<div>
{UNICODE_SYMBOLS.BULLET} <Text strong>{olasRequired}</Text> -
for staking.
</div>
)}
{!hasEnoughEthForInitialFunding && (
<div>
{UNICODE_SYMBOLS.BULLET}{' '}
<Text strong>{nativeTokenRequired}</Text> - for trading.
</div>
)}
</Flex>

{masterSafeAddress && (
<InlineBanner
text="Your safe address"
address={masterSafeAddress}
/>
)}
</Flex>
}
type="primary"
/>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { useMemo } from 'react';

import { useChainDetails } from '@/hooks/useChainDetails';
import { useServices } from '@/hooks/useServices';
import { useMasterWalletContext } from '@/hooks/useWallet';

export const useLowFundsDetails = () => {
const { selectedAgentConfig } = useServices();
const homeChainId = selectedAgentConfig.evmHomeChainId;

const { masterSafes } = useMasterWalletContext();

// master safe details
const selectedMasterSafe = useMemo(() => {
if (!masterSafes) return;
if (!homeChainId) return;

return masterSafes.find(
(masterSafe) => masterSafe.evmChainId === homeChainId,
);
}, [masterSafes, homeChainId]);

// current chain details
const { name: chainName, symbol: tokenSymbol } = useChainDetails(homeChainId);

return {
chainName,
tokenSymbol,
masterSafeAddress: selectedMasterSafe?.address,
};
};
Loading

0 comments on commit 7cb42a7

Please sign in to comment.