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: better history #98

Merged
merged 4 commits into from
Dec 2, 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
23 changes: 7 additions & 16 deletions components/bank/components/__tests__/historyBox.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ mock.module('@/hooks', () => ({
],
},
}),
useSendTxIncludingAddressQuery: () => ({
useGetFilteredTxAndSuccessfulProposals: () => ({
sendTxs: mockTransactions,
totalPages: 1,
isLoading: false,
Expand All @@ -31,19 +31,16 @@ mock.module('@/hooks', () => ({
describe('HistoryBox', () => {
afterEach(() => {
cleanup();
mock.restore();
});

test('renders correctly', () => {
renderWithChainProvider(
<HistoryBox isLoading={false} send={mockTransactions} address="address1" />
);
renderWithChainProvider(<HistoryBox isLoading={false} address="address1" />);
expect(screen.getByText('Transaction History')).toBeTruthy();
});

test('displays transactions', () => {
renderWithChainProvider(
<HistoryBox isLoading={false} send={mockTransactions} address="address1" />
);
renderWithChainProvider(<HistoryBox isLoading={false} address="address1" />);

const sentText = screen.getByText('Sent');
const receivedText = screen.getByText('Received');
Expand All @@ -53,9 +50,7 @@ describe('HistoryBox', () => {
});

test('opens modal when clicking on a transaction', () => {
renderWithChainProvider(
<HistoryBox isLoading={false} send={mockTransactions} address="address1" />
);
renderWithChainProvider(<HistoryBox isLoading={false} address="address1" />);

const transactionElement = screen.getByText('Sent').closest('div[role="button"]');

Expand All @@ -66,9 +61,7 @@ describe('HistoryBox', () => {
});

test('formats amount correctly', () => {
renderWithChainProvider(
<HistoryBox isLoading={false} send={mockTransactions} address="address1" />
);
renderWithChainProvider(<HistoryBox isLoading={false} address="address1" />);

const sentAmount = screen.queryByText('-1 TOKEN');
const receivedAmount = screen.queryByText('+2 TOKEN');
Expand All @@ -78,9 +71,7 @@ describe('HistoryBox', () => {
});

test('displays both sent and received transactions', () => {
renderWithChainProvider(
<HistoryBox isLoading={false} send={mockTransactions} address="address1" />
);
renderWithChainProvider(<HistoryBox isLoading={false} address="address1" />);

const sentText = screen.getByText('Sent');
const receivedText = screen.getByText('Received');
Expand Down
121 changes: 97 additions & 24 deletions components/bank/components/historyBox.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import React, { useState, useMemo } from 'react';
import React, { useMemo, useState } from 'react';
import { TruncatedAddressWithCopy } from '@/components/react/addressCopy';
import TxInfoModal from '../modals/txInfo';
import { shiftDigits, truncateString } from '@/utils';
import { formatDenom } from '@/components';
import { useTokenFactoryDenomsMetadata } from '@/hooks';
import { SendIcon, ReceiveIcon } from '@/components/icons';

import { DenomImage } from '@/components';
import { useSendTxIncludingAddressQuery } from '@/hooks';
import { BurnIcon, DenomImage, formatDenom, MintIcon } from '@/components';
import {
HistoryTxType,
useGetFilteredTxAndSuccessfulProposals,
useTokenFactoryDenomsMetadata,
} from '@/hooks';
import { ReceiveIcon, SendIcon } from '@/components/icons';
import { useEndpointStore } from '@/store/endpointStore';

interface Transaction {
tx_type: HistoryTxType;
from_address: string;
to_address: string;
amount: Array<{ amount: string; denom: string }>;
Expand Down Expand Up @@ -45,23 +48,24 @@

export function HistoryBox({
isLoading: initialLoading,
send,
address,
}: {
isLoading: boolean;
send: TransactionGroup[];
address: string;
}) {
const [selectedTx, setSelectedTx] = useState<TransactionGroup | null>(null);
const [currentPage, setCurrentPage] = useState(1);
const pageSize = 10;

const { selectedEndpoint } = useEndpointStore();
const indexerUrl = selectedEndpoint?.indexer || '';

const {
sendTxs,
totalPages,
isLoading: txLoading,
isError,
} = useSendTxIncludingAddressQuery(address, undefined, currentPage, pageSize);
} = useGetFilteredTxAndSuccessfulProposals(indexerUrl, address, currentPage, pageSize);

const isLoading = initialLoading || txLoading;

Expand Down Expand Up @@ -91,6 +95,71 @@
return groups;
}, [sendTxs]);

function getTransactionIcon(tx: TransactionGroup, address: string) {
if (tx.data.tx_type === HistoryTxType.SEND) {
return tx.data.from_address === address ? <SendIcon /> : <ReceiveIcon />;
} else if (tx.data.tx_type === HistoryTxType.MINT || tx.data.tx_type === HistoryTxType.PAYOUT) {
return (
<MintIcon
className={`w-6 h-6 p-1 border-[#00FFAA] border-opacity-[0.12] border-[1.5px] bg-[#00FFAA] bg-opacity-[0.06] rounded-sm text-green-500`}
/>

Check warning on line 105 in components/bank/components/historyBox.tsx

View check run for this annotation

Codecov / codecov/patch

components/bank/components/historyBox.tsx#L101-L105

Added lines #L101 - L105 were not covered by tests
);
} else if (
tx.data.tx_type === HistoryTxType.BURN ||
tx.data.tx_type === HistoryTxType.BURN_HELD_BALANCE
) {
return (
<BurnIcon className="w-6 h-6 p-1 border-[#F54562] border-[1.5px] border-opacity-[0.12] bg-[#f54562] bg-opacity-[0.06] rounded-sm text-red-500" />

Check warning on line 112 in components/bank/components/historyBox.tsx

View check run for this annotation

Codecov / codecov/patch

components/bank/components/historyBox.tsx#L107-L112

Added lines #L107 - L112 were not covered by tests
);
}

Check warning on line 114 in components/bank/components/historyBox.tsx

View check run for this annotation

Codecov / codecov/patch

components/bank/components/historyBox.tsx#L114

Added line #L114 was not covered by tests
return null;
}

// Get the history message based on the transaction type
function getTransactionMessage(tx: TransactionGroup, address: string) {
if (tx.data.tx_type === HistoryTxType.SEND) {
return tx.data.from_address === address ? 'Sent' : 'Received';
} else if (tx.data.tx_type === HistoryTxType.MINT || tx.data.tx_type === HistoryTxType.PAYOUT) {
return 'Minted';
} else if (
tx.data.tx_type === HistoryTxType.BURN ||
tx.data.tx_type === HistoryTxType.BURN_HELD_BALANCE
) {
return 'Burned';
}

Check warning on line 129 in components/bank/components/historyBox.tsx

View check run for this annotation

Codecov / codecov/patch

components/bank/components/historyBox.tsx#L122-L129

Added lines #L122 - L129 were not covered by tests
return 'Unsupported';
}

// Get the transaction direction based on the transaction type
function getTransactionPlusMinus(tx: TransactionGroup, address: string) {
if (tx.data.tx_type === HistoryTxType.SEND) {
return tx.data.from_address === address ? '-' : '+';
} else if (tx.data.tx_type === HistoryTxType.MINT || tx.data.tx_type === HistoryTxType.PAYOUT) {
return '+';
} else if (
tx.data.tx_type === HistoryTxType.BURN ||
tx.data.tx_type === HistoryTxType.BURN_HELD_BALANCE
) {
return '-';
}

Check warning on line 144 in components/bank/components/historyBox.tsx

View check run for this annotation

Codecov / codecov/patch

components/bank/components/historyBox.tsx#L137-L144

Added lines #L137 - L144 were not covered by tests
return '!!';
}

// Get the transaction color based on the transaction type and direction
function getTransactionColor(tx: TransactionGroup, address: string) {
if (tx.data.tx_type === HistoryTxType.SEND) {
return tx.data.from_address === address ? 'text-red-500' : 'text-green-500';
} else if (tx.data.tx_type === HistoryTxType.MINT || tx.data.tx_type === HistoryTxType.PAYOUT) {
return 'text-green-500';
} else if (
tx.data.tx_type === HistoryTxType.BURN ||
tx.data.tx_type === HistoryTxType.BURN_HELD_BALANCE
) {
return 'text-red-500';
}

Check warning on line 159 in components/bank/components/historyBox.tsx

View check run for this annotation

Codecov / codecov/patch

components/bank/components/historyBox.tsx#L152-L159

Added lines #L152 - L159 were not covered by tests
return null;
}
Comment on lines +98 to +161
Copy link
Contributor

@coderabbitai coderabbitai bot Dec 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add unit tests for transaction helper functions

The newly added functions getTransactionIcon, getTransactionMessage, getTransactionPlusMinus, and getTransactionColor are essential for correctly rendering transaction details based on tx_type. Currently, these functions are not covered by unit tests. To ensure reliability and prevent future regressions, please add unit tests for these functions.

Would you like assistance in creating these unit tests?

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 101-105: components/bank/components/historyBox.tsx#L101-L105
Added lines #L101 - L105 were not covered by tests


[warning] 107-112: components/bank/components/historyBox.tsx#L107-L112
Added lines #L107 - L112 were not covered by tests


[warning] 114-114: components/bank/components/historyBox.tsx#L114
Added line #L114 was not covered by tests


[warning] 122-129: components/bank/components/historyBox.tsx#L122-L129
Added lines #L122 - L129 were not covered by tests


[warning] 137-144: components/bank/components/historyBox.tsx#L137-L144
Added lines #L137 - L144 were not covered by tests


[warning] 152-159: components/bank/components/historyBox.tsx#L152-L159
Added lines #L152 - L159 were not covered by tests

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create a new ticket and create those unit tests.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fmorency, I've created a new GitHub issue to track the addition of these unit tests: #101.

🔗 Analysis chain

Understood, @fmorency. I'll create a new GitHub issue to track the addition of these unit tests.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Open a new GitHub issue to add unit tests for transaction helper functions
gh issue create --title "Add unit tests for transaction helper functions" --body $'The functions `getTransactionIcon`, `getTransactionMessage`, `getTransactionPlusMinus`, and `getTransactionColor` in `historyBox.tsx` need unit tests to ensure reliability and prevent future regressions.\n\nRelated PR: https://github.com/liftedinit/manifest-app/pull/98\nRelated Comment: https://github.com/liftedinit/manifest-app/pull/98#discussion_r1866352991\n\nRequested by: @fmorency' --assignee fmorency

Length of output: 542

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Write the unit tests and add them to the issue.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fmorency, here are the unit tests for the transaction helper functions. I've also added them to issue #101.

// components/bank/components/__tests__/historyBox.test.tsx

import React from 'react';
import {
  getTransactionIcon,
  getTransactionMessage,
  getTransactionPlusMinus,
  getTransactionColor,
  TransactionGroup,
} from '../historyBox';
import { HistoryTxType } from '@/hooks';
import { SendIcon, ReceiveIcon, MintIcon, BurnIcon } from '@/components/icons';

describe('Transaction Helper Functions', () => {
  const address = 'manifest1abc';

  const createTransactionGroup = (
    txType: HistoryTxType,
    fromAddress: string,
    toAddress: string
  ): TransactionGroup => ({
    tx_hash: 'dummyhash',
    block_number: 123456,
    formatted_date: '2023-10-05',
    data: {
      tx_type: txType,
      from_address: fromAddress,
      to_address: toAddress,
      amount: [{ amount: '1000000', denom: 'utoken' }],
    },
  });

  describe('getTransactionIcon', () => {
    it('should return SendIcon when tx_type is SEND and from_address matches the address', () => {
      const tx = createTransactionGroup(HistoryTxType.SEND, address, 'manifest1def');
      const icon = getTransactionIcon(tx, address);
      expect(icon?.type).toBe(SendIcon);
    });

    it('should return ReceiveIcon when tx_type is SEND and from_address does not match the address', () => {
      const tx = createTransactionGroup(HistoryTxType.SEND, 'manifest1def', address);
      const icon = getTransactionIcon(tx, address);
      expect(icon?.type).toBe(ReceiveIcon);
    });

    it('should return MintIcon when tx_type is MINT or PAYOUT', () => {
      const txMint = createTransactionGroup(HistoryTxType.MINT, 'from', 'to');
      const txPayout = createTransactionGroup(HistoryTxType.PAYOUT, 'from', 'to');
      const iconMint = getTransactionIcon(txMint, address);
      const iconPayout = getTransactionIcon(txPayout, address);
      expect(iconMint?.type).toBe(MintIcon);
      expect(iconPayout?.type).toBe(MintIcon);
    });

    it('should return BurnIcon when tx_type is BURN or BURN_HELD_BALANCE', () => {
      const txBurn = createTransactionGroup(HistoryTxType.BURN, 'from', 'to');
      const txBurnHeld = createTransactionGroup(HistoryTxType.BURN_HELD_BALANCE, 'from', 'to');
      const iconBurn = getTransactionIcon(txBurn, address);
      const iconBurnHeld = getTransactionIcon(txBurnHeld, address);
      expect(iconBurn?.type).toBe(BurnIcon);
      expect(iconBurnHeld?.type).toBe(BurnIcon);
    });

    it('should return null for unsupported tx_type', () => {
      const tx = createTransactionGroup('UNSUPPORTED' as HistoryTxType, 'from', 'to');
      const icon = getTransactionIcon(tx, address);
      expect(icon).toBeNull();
    });
  });

  describe('getTransactionMessage', () => {
    it('should return "Sent" when tx_type is SEND and from_address matches the address', () => {
      const tx = createTransactionGroup(HistoryTxType.SEND, address, 'manifest1def');
      const message = getTransactionMessage(tx, address);
      expect(message).toBe('Sent');
    });

    it('should return "Received" when tx_type is SEND and from_address does not match the address', () => {
      const tx = createTransactionGroup(HistoryTxType.SEND, 'manifest1def', address);
      const message = getTransactionMessage(tx, address);
      expect(message).toBe('Received');
    });

    it('should return "Minted" when tx_type is MINT or PAYOUT', () => {
      const txMint = createTransactionGroup(HistoryTxType.MINT, 'from', 'to');
      const txPayout = createTransactionGroup(HistoryTxType.PAYOUT, 'from', 'to');
      const messageMint = getTransactionMessage(txMint, address);
      const messagePayout = getTransactionMessage(txPayout, address);
      expect(messageMint).toBe('Minted');
      expect(messagePayout).toBe('Minted');
    });

    it('should return "Burned" when tx_type is BURN or BURN_HELD_BALANCE', () => {
      const txBurn = createTransactionGroup(HistoryTxType.BURN, 'from', 'to');
      const txBurnHeld = createTransactionGroup(HistoryTxType.BURN_HELD_BALANCE, 'from', 'to');
      const messageBurn = getTransactionMessage(txBurn, address);
      const messageBurnHeld = getTransactionMessage(txBurnHeld, address);
      expect(messageBurn).toBe('Burned');
      expect(messageBurnHeld).toBe('Burned');
    });

    it('should return "Unsupported" for unsupported tx_type', () => {
      const tx = createTransactionGroup('UNSUPPORTED' as HistoryTxType, 'from', 'to');
      const message = getTransactionMessage(tx, address);
      expect(message).toBe('Unsupported');
    });
  });

  describe('getTransactionPlusMinus', () => {
    it('should return "-" when tx_type is SEND and from_address matches the address', () => {
      const tx = createTransactionGroup(HistoryTxType.SEND, address, 'to');
      const result = getTransactionPlusMinus(tx, address);
      expect(result).toBe('-');
    });

    it('should return "+" when tx_type is SEND and from_address does not match the address', () => {
      const tx = createTransactionGroup(HistoryTxType.SEND, 'from', address);
      const result = getTransactionPlusMinus(tx, address);
      expect(result).toBe('+');
    });

    it('should return "+" when tx_type is MINT or PAYOUT', () => {
      const txMint = createTransactionGroup(HistoryTxType.MINT, 'from', 'to');
      const txPayout = createTransactionGroup(HistoryTxType.PAYOUT, 'from', 'to');
      const resultMint = getTransactionPlusMinus(txMint, address);
      const resultPayout = getTransactionPlusMinus(txPayout, address);
      expect(resultMint).toBe('+');
      expect(resultPayout).toBe('+');
    });

    it('should return "-" when tx_type is BURN or BURN_HELD_BALANCE', () => {
      const txBurn = createTransactionGroup(HistoryTxType.BURN, 'from', 'to');
      const txBurnHeld = createTransactionGroup(HistoryTxType.BURN_HELD_BALANCE, 'from', 'to');
      const resultBurn = getTransactionPlusMinus(txBurn, address);
      const resultBurnHeld = getTransactionPlusMinus(txBurnHeld, address);
      expect(resultBurn).toBe('-');
      expect(resultBurnHeld).toBe('-');
    });

    it('should return "!!" for unsupported tx_type', () => {
      const tx = createTransactionGroup('UNSUPPORTED' as HistoryTxType, 'from', 'to');
      const result = getTransactionPlusMinus(tx, address);
      expect(result).toBe('!!');
    });
  });

  describe('getTransactionColor', () => {
    it('should return "text-red-500" when tx_type is SEND and from_address matches the address', () => {
      const tx = createTransactionGroup(HistoryTxType.SEND, address, 'to');
      const color = getTransactionColor(tx, address);
      expect(color).toBe('text-red-500');
    });

    it('should return "text-green-500" when tx_type is SEND and from_address does not match the address', () => {
      const tx = createTransactionGroup(HistoryTxType.SEND, 'from', address);
      const color = getTransactionColor(tx, address);
      expect(color).toBe('text-green-500');
    });

    it('should return "text-green-500" when tx_type is MINT or PAYOUT', () => {
      const txMint = createTransactionGroup(HistoryTxType.MINT, 'from', 'to');
      const txPayout = createTransactionGroup(HistoryTxType.PAYOUT, 'from', 'to');
      const colorMint = getTransactionColor(txMint, address);
      const colorPayout = getTransactionColor(txPayout, address);
      expect(colorMint).toBe('text-green-500');
      expect(colorPayout).toBe('text-green-500');
    });

    it('should return "text-red-500" when tx_type is BURN or BURN_HELD_BALANCE', () => {
      const txBurn = createTransactionGroup(HistoryTxType.BURN, 'from', 'to');
      const txBurnHeld = createTransactionGroup(HistoryTxType.BURN_HELD_BALANCE, 'from', 'to');
      const colorBurn = getTransactionColor(txBurn, address);
      const colorBurnHeld = getTransactionColor(txBurnHeld, address);
      expect(colorBurn).toBe('text-red-500');
      expect(colorBurnHeld).toBe('text-red-500');
    });

    it('should return null for unsupported tx_type', () => {
      const tx = createTransactionGroup('UNSUPPORTED' as HistoryTxType, 'from', 'to');
      const color = getTransactionColor(tx, address);
      expect(color).toBeNull();
    });
  });
});


return (
<div className="w-full mx-auto rounded-[24px] h-full flex flex-col">
<div className="flex items-center justify-between mb-4">
Expand Down Expand Up @@ -206,7 +275,7 @@
>
<div className="flex items-center space-x-3">
<div className="w-8 h-8 rounded-full overflow-hidden flex items-center justify-center">
{tx.data.from_address === address ? <SendIcon /> : <ReceiveIcon />}
{getTransactionIcon(tx, address)}
</div>
<div className="w-10 h-10 rounded-full overflow-hidden bg-[#0000000A] dark:bg-[#FFFFFF0F] flex items-center justify-center">
{tx.data.amount.map((amt, index) => {
Expand All @@ -217,7 +286,7 @@
<div className="">
<div className="flex flex-row items-center gap-2">
<p className="font-semibold text-[#161616] dark:text-white">
{tx.data.from_address === address ? 'Sent' : 'Received'}
{getTransactionMessage(tx, address)}
</p>
<p className="font-semibold text-[#161616] dark:text-white">
{tx.data.amount.map((amt, index) => {
Expand All @@ -234,22 +303,26 @@
</p>
</div>
<div className="address-copy" onClick={e => e.stopPropagation()}>
<TruncatedAddressWithCopy
address={
tx.data.from_address === address
? tx.data.to_address
: tx.data.from_address
}
slice={6}
/>
{tx.data.from_address.startsWith('manifest1') ? (
<TruncatedAddressWithCopy
address={
tx.data.from_address === address
? tx.data.to_address
: tx.data.from_address

Check warning on line 311 in components/bank/components/historyBox.tsx

View check run for this annotation

Codecov / codecov/patch

components/bank/components/historyBox.tsx#L307-L311

Added lines #L307 - L311 were not covered by tests
}
slice={6}

Check warning on line 313 in components/bank/components/historyBox.tsx

View check run for this annotation

Codecov / codecov/patch

components/bank/components/historyBox.tsx#L313

Added line #L313 was not covered by tests
/>
) : (
<div className="text-[#00000099] dark:text-[#FFFFFF99]">
{tx.data.from_address}
</div>
)}
</div>
</div>
</div>
<div className="text-right">
<p
className={`font-semibold ${tx.data.from_address === address ? 'text-red-500' : 'text-green-500'}`}
>
{tx.data.from_address === address ? '-' : '+'}
<p className={`font-semibold ${getTransactionColor(tx, address)}`}>
{getTransactionPlusMinus(tx, address)}
{tx.data.amount
.map(amt => {
const metadata = metadatas?.metadatas.find(
Expand Down
41 changes: 35 additions & 6 deletions components/bank/modals/txInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { TruncatedAddressWithCopy } from '@/components/react/addressCopy';
import { formatDenom, TransactionGroup } from '@/components';
import { FaExternalLinkAlt } from 'react-icons/fa';
import { shiftDigits } from '@/utils';
import { useEndpointStore } from '@/store/endpointStore';

interface TxInfoModalProps {
tx: TransactionGroup;
Expand All @@ -11,6 +12,9 @@ interface TxInfoModalProps {
}

export default function TxInfoModal({ tx, modalId }: TxInfoModalProps) {
const { selectedEndpoint } = useEndpointStore();
const explorerUrl = selectedEndpoint?.explorer || '';

function formatDate(dateString: string): string {
const date = new Date(dateString);
return date.toLocaleString('en-US', {
Expand Down Expand Up @@ -39,13 +43,36 @@ export default function TxInfoModal({ tx, modalId }: TxInfoModalProps) {
</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<InfoItem label="TRANSACTION HASH" value={tx?.tx_hash} isAddress={true} />
<InfoItem label="BLOCK" value={tx?.block_number?.toString()} />
<InfoItem label="TIMESTAMP" value={formatDate(tx?.formatted_date)} />
<InfoItem
label="TRANSACTION HASH"
explorerUrl={explorerUrl}
value={tx?.tx_hash}
isAddress={true}
/>
<InfoItem
label="BLOCK"
explorerUrl={explorerUrl}
value={tx?.block_number?.toString()}
/>
<InfoItem
label="TIMESTAMP"
explorerUrl={explorerUrl}
value={formatDate(tx?.formatted_date)}
/>
</div>
<div>
<InfoItem label="FROM" value={tx?.data?.from_address} isAddress={true} />
<InfoItem label="TO" value={tx?.data?.to_address} isAddress={true} />
<InfoItem
label="FROM"
explorerUrl={explorerUrl}
value={tx?.data?.from_address}
isAddress={true}
/>
<InfoItem
label="TO"
explorerUrl={explorerUrl}
value={tx?.data?.to_address}
isAddress={true}
/>
<div>
<p className="text-sm font-semibold text-[#00000099] dark:text-[#FFFFFF99] mb-2">
VALUE
Expand Down Expand Up @@ -74,10 +101,12 @@ export default function TxInfoModal({ tx, modalId }: TxInfoModalProps) {
function InfoItem({
label,
value,
explorerUrl,
isAddress = false,
}: {
label: string;
value: string;
explorerUrl: string;
isAddress?: boolean;
}) {
return (
Expand All @@ -88,7 +117,7 @@ function InfoItem({
<div className="flex items-center">
<TruncatedAddressWithCopy address={value} slice={8} />
<a
href={`${process.env.NEXT_PUBLIC_TESTNET_EXPLORER_URL}/${label === 'TRANSACTION HASH' ? 'transaction' : 'account'}/${label?.includes('TRANSACTION') ? value?.toUpperCase() : value}`}
href={`${explorerUrl}/${label === 'TRANSACTION HASH' ? 'transaction' : 'account'}/${label?.includes('TRANSACTION') ? value?.toUpperCase() : value}`}
target="_blank"
rel="noopener noreferrer"
className="ml-2 text-primary hover:text-primary/50"
Comment on lines +120 to 123
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Simplify complex URL construction logic

The current URL construction logic is complex and hard to maintain. It mixes multiple conditions and string manipulations in a single line.

Consider extracting the logic into a helper function:

+ const getExplorerLink = (explorerUrl: string, label: string, value: string) => {
+   const type = label === 'TRANSACTION HASH' ? 'transaction' : 'account';
+   const formattedValue = label?.includes('TRANSACTION') ? value?.toUpperCase() : value;
+   return `${explorerUrl}/${type}/${formattedValue}`;
+ };

- href={`${explorerUrl}/${label === 'TRANSACTION HASH' ? 'transaction' : 'account'}/${label?.includes('TRANSACTION') ? value?.toUpperCase() : value}`}
+ href={getExplorerLink(explorerUrl, label, value)}

Committable suggestion skipped: line range outside the PR's diff.

Expand Down
Loading
Loading