Skip to content

Commit

Permalink
Merge pull request #21 from guilyx/holdings
Browse files Browse the repository at this point in the history
Holdings
  • Loading branch information
guilyx committed Aug 13, 2023
2 parents 7fb2095 + bcbe441 commit 0de76e8
Show file tree
Hide file tree
Showing 21 changed files with 774 additions and 68 deletions.
32 changes: 32 additions & 0 deletions public/chains/ethereum.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/chains/polyhedra.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
67 changes: 67 additions & 0 deletions public/chains/zora.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
37 changes: 37 additions & 0 deletions src/common/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Token } from "../services/explorers/explorer";

const tokenPriceMap: Map<string, number> = new Map();

export function setCommonTokenPrice(symbol: string, price: number) {
tokenPriceMap.set(symbol, price);
}

export function getCommonTokenPrice(symbol: string): number | undefined {
return tokenPriceMap.get(symbol);
}

export function hasCommonTokenPrice(symbol: string): boolean {
return tokenPriceMap.has(symbol);
}

export const MANTLE_TOKEN: Token = {
contractAddress: '0x3c3a81e81dc49A522A592e7622A7E711c06bf354',
name: 'Mantle',
symbol: 'MNT',
type: 'ERC-20',
decimals: 18,
price: undefined,
balance: 0.0,
balanceUsd: undefined,
}

export const ETH_TOKEN: Token = {
contractAddress: '0x4200000000000000000000000000000000000006',
name: 'Ether',
symbol: 'ETH',
type: 'ERC-20',
decimals: 18,
price: undefined,
balance: 0.0,
balanceUsd: undefined,
}
76 changes: 76 additions & 0 deletions src/components/ActivityCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { FC, useEffect, useState } from 'react';
import { Transaction } from '../services/explorers/explorer';
import { countAllTransactionPeriods, getTimeAgo } from '../utils/utils';

interface ActivityCardProps {
address: string;
transactions: Transaction[] | [];
}

const ActivityCard: FC<ActivityCardProps> = ({ address, transactions }) => {
const { days, weeks, months } = countAllTransactionPeriods(address, transactions);
const [lastActivity, setLastActivity] = useState<string>('');

useEffect(() => {
if (!transactions || transactions.length === 0) return;
setLastActivity(getTimeAgo(transactions[0]?.receivedAt));
}, [transactions]);

return (
<div className="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800 h-[245px]">
<div className="block sm:space-x-4 xl:space-x-0 2xl:space-x-4 w-[347px]">
<ul className="max-w-md divide-y divide-gray-200 dark:divide-gray-700">
<li className="pb-3 sm:pb-4">
<div className="flex items-center space-x-4">
<div className="flex-1 min-w-0">
<p className="text-sm font-medium text-gray-900 truncate dark:text-white">Last activity</p>
</div>
<div
className={
'inline-flex items-center text-base font-semibold ' +
(new Date(transactions[0]?.receivedAt).getTime() < new Date().getTime() - 86400 * 7 * 1000
? 'text-red-500 dark:text-red-400'
: 'text-gray-500 dark:text-white')
}
>
{lastActivity}
</div>
</div>
</li>
<li className="py-3 sm:py-4">
<div className="flex items-center space-x-4">
<div className="flex-1 min-w-0">
<p className="text-sm font-medium text-gray-900 truncate dark:text-white">Active day(s)</p>
</div>
<div className="inline-flex items-center text-base font-semibold text-gray-900 dark:text-white">
{days + (days === 1 ? ' day' : ' days')}
</div>
</div>
</li>
<li className="py-3 sm:py-4">
<div className="flex items-center space-x-4">
<div className="flex-1 min-w-0">
<p className="text-sm font-medium text-gray-900 truncate dark:text-white">Active week(s)</p>
</div>
<div className="inline-flex items-center text-base font-semibold text-gray-900 dark:text-white">
{weeks + (weeks === 1 ? ' week' : ' weeks')}
</div>
</div>
</li>
<li className="pt-3 pb-0 sm:pt-4">
<div className="flex items-center space-x-4">
<div className="flex-1 min-w-0">
<p className="text-sm font-medium text-gray-900 truncate dark:text-white">Active month(s)</p>
</div>
<div className="inline-flex items-center text-base font-semibold text-gray-900 dark:text-white">
{months + (months === 1 ? ' month' : ' months')}
</div>
</div>
</li>
</ul>
</div>
</div>
);
};

export default ActivityCard;
106 changes: 106 additions & 0 deletions src/components/BalanceCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { FC, useContext, useEffect, useState } from 'react';
import { getTokenPrice } from '../services/tokenPrice.ts';
import { Token } from '../services/explorers/explorer.ts';

interface TokensCardProps {
address: string
onTokens: Token[]
explorer: string
}

const TokensCard: FC<TokensCardProps> = ({ address, onTokens, explorer }) => {
const [tokens, setTokens] = useState<Token[] | undefined>(undefined);
const [totalBalanceUSD, setTotalBalanceUSD] = useState<number>(0);

useEffect(() => {
const fetchTokens = async () => {

const totalUSD = onTokens.reduce((total, token) => {
if (token.price !== undefined && token.balance && token.decimals && token.balanceUsd) {
const balanceUSD = token.balanceUsd;
return total + balanceUSD;
}
return total;
}, 0);

setTokens(
onTokens
.sort((a, b) => {
if (a.type === b.type) {
if (a.balanceUsd === undefined && b.balanceUsd === undefined) return 0;
if (a.balanceUsd === undefined) return Number(b.balanceUsd);
if (b.balanceUsd === undefined) return Number(a.balanceUsd);
return Number(a.balanceUsd) - Number(b.balanceUsd);
};
if (a.type === 'ERC-20' && b.type !== 'ERC-20') return -1;
if (b.type === 'ERC-20' && a.type !== 'ERC-20') return 1;
return 0;
})
.filter((token) => token.name),
);

setTotalBalanceUSD(totalUSD);
};

fetchTokens();
}, [address, onTokens]);

return (
<div className="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800 h-[245px] overflow-auto scrollbar">
<div className="block sm:space-x-4 xl:space-x-0 2xl:space-x-4 w-[339px]">
<ul className="max-w-md divide-y divide-gray-200 dark:divide-gray-700">
{!tokens && <h1 className="text-center text-2xl text-white">Impossible to load token</h1>}
{totalBalanceUSD !== 0 && (
<div className="text-center text-gray-500 dark:text-white mb-4 text-xl">
Total Balance: ${totalBalanceUSD.toFixed(2)}
</div>
)}
{tokens &&
tokens.map((token, index) => {
return (
<li
className={
!totalBalanceUSD && !index
? 'pb-3 sm:pb-4'
: index === tokens.length - 1
? 'pt-3 sm:pt-4'
: 'py-3 sm:pt-4'
}
key={index}
>
<div
className="flex items-center space-x-4 cursor-pointer"
onClick={() => {
window.open(explorer+ '/address/' + token.contractAddress, '_blank');
}}
>
<div className="flex-1 min-w-0">
<div className="flex">
<p className="text-sm font-medium text-gray-900 truncate dark:text-white">{token.symbol}</p>
{token.type === 'ERC-721' && (
<span className="inline-flex items-center justify-center px-2 py-0.5 ml-3 text-xs font-medium text-blue-500 bg-gray-200 rounded dark:bg-gray-700 dark:text-blue-400">
NFT
</span>
)}
</div>
<p className="text-sm text-gray-500 truncate dark:text-gray-400">{token.name}</p>
</div>
<div className="inline-flex flex-col items-end text-base font-semibold text-gray-900 dark:text-white">
<div>{token.decimals ? (token.balance * 10 ** -token.decimals).toFixed(3) : token.balance}</div>
{token.price !== undefined && (
<div className="text-xs text-gray-500 dark:text-gray-400">
${((token.price || 0) * (token.balance * 10 ** -token.decimals)).toFixed(2)}
</div>
)}
</div>
</div>
</li>
);
})}
</ul>
</div>
</div>
);
};

export default TokensCard;
1 change: 1 addition & 0 deletions src/components/ChainTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const ChainTabs: React.FC<ChainTabsProps> = ({ selectedTab, setSelectedTab }) =>
{ name: 'zkEvm', logo: './chains/zkevm.svg' },
{ name: 'Mantle', logo: './chains/mantle.svg' },
{ name: 'Base', logo: './chains/base.svg' },
{ name: 'Zora (UC)', logo: './chains/zora.svg'},
// { name: 'StarkNet (UC)', logo: './chains/starknet.svg' },
{ name: 'Scroll (TN)', logo: './chains/scroll.svg' },
{ name: 'Taiko (TN)', logo: './chains/taiko.svg'},
Expand Down
6 changes: 1 addition & 5 deletions src/components/VolumeCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,7 @@ const VolumeCard: FC<VolumeCardProps> = ({ address, transactions }) => {
parseInt(a.amount) * 10 ** -a.token.decimals * a.token.price,
);
if (transfers.length === 0) return;
console.log("Name: ", transfers[0].token.name);
console.log("Amount: ", transfers[0].amount);
console.log("Decimals ", transfers[0].token.decimals);
console.log("Price ", transfers[0].token.price);
console.log("True Amount ", parseInt(transfers[0].amount) * 10 ** -transfers[0].token.decimals);

const tmpVolume = parseInt(transfers[0].amount) * 10 ** -transfers[0].token.decimals * transfers[0].token.price;
setVolume((prev) => prev + tmpVolume);
if (new Date(transaction.receivedAt).getTime() >= new Date().getTime() - 86400 * 7 * 1000) {
Expand Down
17 changes: 0 additions & 17 deletions src/contexts/global_context.ts

This file was deleted.

Loading

0 comments on commit 0de76e8

Please sign in to comment.