Skip to content

Commit

Permalink
TW-1479: [EVM] Transactions history with Alchemy (#1231)
Browse files Browse the repository at this point in the history
* TW-1479: [EVM] Transactions history

* TW-1479: [EVM] Transactions history. Refactor

* TW-1479: [EVM] Transactions history. ++ Parsing

* TW-1479: [EVM] Transaction history. + Extra icon SRC from API

* TW-1479: [EVM] Transaction history. Refactor. Assets Images Components

* TW-1479: [EVM] Transactions history. Minor fixes

* TW-1479: [EVM] Transaction history. + Gas operation

* TW-1479: [EVM] Transactions history. [Tezos] Formatting activities. [EVM] Applying metadata.

* TW-1479: [EVM] Transactions history. [EVM] + InfiniteScroll

* TW-1479: [EVM] Transaction history. Token page

* TW-1479: [EVM] Transaction history. API calls. Refactor. With nextPage

* TW-1479: [EVM] Transaction history. Token page. Using endpoint V2

* TW-1479: [EVM] Transactions history. [Tezos] Fix 'receive' operations

* TW-1479: [EVM] Transactions history. [Tezos] Refactor

* TW-1479: [EVM] Transactions history. [Tezos] Clean-up

* TW-1479: [EVM] Transactions history. [Tezos] -- lib/temple/activity

* TW-1479: [EVM] Transactions history. [Tezos] + Approve

* TW-1479: [EVM] Transactions history. + Kind 'Transfer'

* TW-1479: [EVM] Transactions history. [Tezos] Restored opers order. Reversed back

* TW-1479: [EVM] Transactions history. Fix InfiniteScroll

* TW-1479: [EVM] Transactions history. [EVM] + TransferSingle support

* TW-1479: [EVM] Transactions history. Refactor. OperationBaseComponent

* TW-1479: [EVM] Transactions history. [Tezos] + Bundles

* TW-1479: [EVM] Transactions history. [Tezos] Token page. -- Asset icons

* TW-1479: [EVM] Transactions history. [EVM] + Bundles

* TW-1479: [EVM] Transactions history. Explore Tab -> Page

* TW-1479: [EVM] Transactions history. Filters. By network.  WIP

* TW-1479: [EVM] Transactions history. Multichain. WIP: For EVM

* TW-1479: [EVM] Transactions history. Multichain. EVM. Optimization: loops reduction

* TW-1479: [EVM] Transactions history. Multichain. + AbortSignal

* TW-1479: [EVM] Transactions history. Multichain. + useActivitiesLoadingLogic()

* TW-1479: [EVM] Transactions history. InfiniteScroll. Fix loader show-up

* TW-1479: [EVM] Transactions history. Multichain. Refactor

* TW-1479: [EVM] Transactions history. Approve kind. + Unlimited

* TW-1479: [EVM] Transactions history. Amounts crypto & fiat

* TW-1479: [EVM] Transactions history. Filters. WIP

* TW-1479: [EVM] Transactions history. Refactor

* TW-1479: [EVM] Transactions history. Refactor

* TW-1479: [EVM] Transactions history. Refactor

* TW-1479: [EVM] Transactions history. Filters. Networks dropdown

* TW-1479: [EVM] Transactions history. Refactor NetworkIcon tooltips

* TW-1479: [EVM] Transactions history. Bundle modal. ++

* TW-1479: [EVM] Transactions history. Multichain list. + Ad

* TW-1479: [EVM] Transactions history. + @covalenthq/client-sdk

* TW-1479: [EVM] Transactions history. Refactor

* TW-1479: [EVM] Transactions history. + Grouping by Date

* TW-1479: [EVM] Transactions history. Fix amountSigned. + Green positive amounts

* TW-1479: [EVM] Transactions history. + Bundle icons stack. + NFTs rounding

* TW-1479: [EVM] Transactions history. ++ Asset Images

* TW-1479: [EVM] Transactions history. Fix pipeline

* TW-1479: [EVM] Transactions history. Trigger pipeline

* TW-1479: [EVM] Transactions history. Trigger pipeline

* TW-1479: [EVM] Transactions history. Minor design fixes

* TW-1479: [EVM] Transactions history. + Activity status tag elem

* TW-1479: [EVM] Transactions history. + Address chips in Bundle modal

* TW-1479: [EVM] Transactions history. Refactor. + Transfer types

* TW-1479: [EVM] Transactions history. Refactor. Transfer types

* TW-1479: [EVM] Transactions history. Minor fixes

* TW-1479: [EVM] Transactions history. Multichain. + Fallback icons

* TW-1479: [EVM] Transactions history. + New loader

* TW-1479: [EVM] Transactions history. Multichain. -- Filters by kind

* TW-1479: [EVM] Transactions history. Fix merge

* TW-1479: [EVM] Transactions history. Refactor

* TW-1479: [EVM] Transactions history. Refactor

* TW-1479: [EVM] Transactions history. Multichain. Refactor

* TW-1479: [EVM] Transactions history. Refactor

* TW-1479: [EVM] Transactions history. Refactor

* Fix audit-deps

* TW-1479: [EVM] Transactions history. Minor fixes

* TW-1479: [EVM] Transactions history. Reduced number of checksumming addresses while parsing

* TW-1479: [EVM] Transactions history. Eliminated checksumming addresses while parsing

* TW-1479: [EVM] Transactions history. Bundle modal. + Lazy render

* TW-1479: [EVM] Transactions history. Minor refactor

* fix after merge

* TW-1587: [research] Activity History on Alchemy. Transfers

* TW-1587: [research] Activity History on Alchemy. Multichain

* TW-1587: [research] Activity History on Alchemy. + Approvals

* TW-1479: [EVM] Transactions history with Alchemy. -- Covalent SDK

* TW-1479: [EVM] Transactions history with Alchemy. Merging from/to transfers correctly

* TW-1479: [EVM] Transactions history with Alchemy. ++ Merging transfers

* TW-1479: [EVM] Transactions history with Alchemy. + Sort by log index

* TW-1587: [research] Activity History on Alchemy. + Block Explorer URLs

* TW-1479: [EVM] Transactions history with Alchemy

* TW-1479: [EVM] Transactions history with Alchemy. Removed 'alchemy-sdk'

* TW-1479: [EVM] Transactions history with Alchemy. Return Optimism to def networks

* TW-1479: [EVM] Transactions history with Alchemy. Minor fixes

* TW-1479: [EVM] Transactions history with Alchemy. Transfer -> Send/Receive

* TW-1479: [EVM] Transactions history with Alchemy. Refactor

* fix pipeline

* TW-1479: [EVM] Transactions history with Alchemy. Fix Firefox lag
  • Loading branch information
alex-tsx authored Dec 6, 2024
1 parent c55dece commit a3be6fe
Show file tree
Hide file tree
Showing 176 changed files with 4,110 additions and 2,327 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@
"ts-prune": "^0.10.3",
"typescript": "^5.4.2",
"typescript-eslint": "^7",
"use-debounce": "7.0.1",
"use-debounce": "^10",
"use-force-update": "1.0.7",
"use-onclickoutside": "0.4.1",
"util": "0.11.1",
Expand Down
4 changes: 0 additions & 4 deletions public/_locales/de/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -454,10 +454,6 @@
"message": "Tezos Mainnet",
"description": "Mainnet = main network"
},
"marigoldMainnet": {
"message": "Marigold Mainnet",
"description": "Mainnet = main network"
},
"templeWalletOptions": {
"message": "Temple Wallet | Optionen"
},
Expand Down
1 change: 1 addition & 0 deletions public/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -2469,6 +2469,7 @@
"blockExplorer": {
"message": "Block Explorer"
},
"viewOnExplorer": { "message": "View on explorer" },
"viewOnBlockExplorer": { "message": "View on block explorer" },
"specifyTokenId": {
"message": "Specify token ID"
Expand Down
3 changes: 3 additions & 0 deletions public/_locales/uk/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -1943,5 +1943,8 @@
},
"zarName": {
"message": "Південноафриканський ранд"
},
"allNetworks": {
"message": "Всі мережі"
}
}
2 changes: 2 additions & 0 deletions src/app/PageRouter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { useTempleClient } from 'lib/temple/front';
import * as Woozie from 'lib/woozie';
import { TempleChainKind } from 'temple/types';

import { ActivityPage } from './pages/Activity';
import { ChainSettings } from './pages/ChainSettings';
import { ImportWallet } from './pages/ImportWallet';
import { Market } from './pages/Market';
Expand Down Expand Up @@ -75,6 +76,7 @@ const ROUTE_MAP = Woozie.createMap<RouteContext>([
<Home chainKind={chainKind} chainId={chainId} assetSlug={assetSlug} />
))
],
['/activity', onlyReady(() => <ActivityPage />)],
['/connect-ledger', onlyReady(onlyInFullPage(() => <ConnectLedger />))],
['/receive', onlyReady(() => <Receive />)],
[
Expand Down
17 changes: 0 additions & 17 deletions src/app/a11y/ContentFader/index.tsx

This file was deleted.

17 changes: 0 additions & 17 deletions src/app/a11y/ContentFader/styles.module.css

This file was deleted.

5 changes: 5 additions & 0 deletions src/app/a11y/content-fader/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import ModStyles from './styles.module.css';

export const ACTIVATE_CONTENT_FADER_CLASSNAME = ModStyles.activateContentFader;

export const FADABLE_CONTENT_CLASSNAME = ModStyles.fadeableContent;
3 changes: 3 additions & 0 deletions src/app/a11y/content-fader/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.activateContentFader .fadeableContent {
filter: brightness(0.85);
}
1 change: 0 additions & 1 deletion src/app/atoms/AccountName.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ interface CopyAddressButtonProps {

const CopyAddressButton = memo<CopyAddressButtonProps>(({ chain, address, onCopy }) => (
<ActionListItem
className="flex items-center"
onClick={() => {
window.navigator.clipboard.writeText(address);
onCopy();
Expand Down
61 changes: 35 additions & 26 deletions src/app/atoms/ActionListItem.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { memo } from 'react';
import React, { FC } from 'react';

import clsx from 'clsx';

Expand All @@ -14,33 +14,42 @@ export interface ActionListItemProps extends PropsWithChildren {
/** Pass it, if you want it to be called with `false` on click too */
setOpened?: SyncFn<boolean>;
testID?: string;
active?: boolean;
danger?: boolean;
}

export const ActionListItem = memo<ActionListItemProps>(
({ Icon, linkTo, className, onClick, setOpened, testID, danger, children }) => {
const baseProps = {
testID,
className: clsx(
'flex items-center py-1.5 px-2 gap-x-1 rounded-md text-font-description',
'hover:bg-secondary-low',
className
),
onClick: setOpened
? () => {
setOpened(false);
onClick?.();
}
: onClick,
children: (
<>
{Icon && <IconBase Icon={Icon} size={16} className={danger ? 'text-error' : 'text-secondary'} />}
export const ActionListItem: FC<ActionListItemProps> = ({
Icon,
linkTo,
className,
onClick,
setOpened,
testID,
active,
danger,
children
}) => {
const baseProps = {
testID,
className: clsx(
'flex items-center py-1.5 px-2 gap-x-1 rounded-md text-font-description',
active ? 'bg-grey-4' : danger ? 'hover:bg-error-low' : 'hover:bg-secondary-low',
className
),
onClick: setOpened
? () => {
setOpened(false);
onClick?.();
}
: onClick,
children: (
<>
{Icon && <IconBase Icon={Icon} size={16} className={danger ? 'text-error' : 'text-secondary'} />}

{typeof children === 'string' ? <span className="capitalize">{children}</span> : children}
</>
)
};
{typeof children === 'string' ? <span className="capitalize">{children}</span> : children}
</>
)
};

return linkTo ? <Link {...baseProps} to={linkTo} /> : <Button {...baseProps} />;
}
);
return linkTo ? <Link {...baseProps} to={linkTo} /> : <Button {...baseProps} />;
};
4 changes: 2 additions & 2 deletions src/app/atoms/Anchor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import * as React from 'react';

import { AnalyticsEventCategory, setTestID, TestIDProps, useAnalytics } from 'lib/analytics';

interface Props
export interface AnchorProps
extends React.PropsWithRef<React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>>,
TestIDProps {
treatAsButton?: boolean;
}

export const Anchor = React.forwardRef<HTMLAnchorElement, Props>(
export const Anchor = React.forwardRef<HTMLAnchorElement, AnchorProps>(
(
{ target = '_blank', rel = 'noopener noreferrer', testID, testIDProperties, treatAsButton, onClick, ...props },
ref
Expand Down
4 changes: 2 additions & 2 deletions src/app/atoms/Avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ export type AvatarProps = AvatarDivProps | AvatarButtonProps;
const sizeButtonClassNames = {
24: 'w-6 h-6 rounded border p-px',
32: 'w-8 h-8 rounded-md border p-px',
60: 'w-15 h-15 rounded-2.5 border-1.5 p-[0.5px]'
60: 'w-15 h-15 rounded-10 border-1.5 p-[0.5px]'
};

const sizeContainerClassNames = {
24: 'rounded-0.75',
24: 'rounded-3',
32: 'rounded',
60: 'rounded-lg border border-white'
};
Expand Down
40 changes: 28 additions & 12 deletions src/app/atoms/Identicon.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
import React, { HTMLAttributes, useMemo } from 'react';
import React, { FC, HTMLAttributes, ImgHTMLAttributes, useMemo } from 'react';

import clsx from 'clsx';

import { IdenticonType, getIdenticonUri } from 'lib/temple/front';
import { IdenticonOptions } from 'lib/temple/front/identicon';
import {
IdenticonImgType,
ImageIdenticonOptions,
InitialsIdenticonOptions,
buildImageIdenticonUri,
buildInitialsIdenticonUri
} from 'lib/identicon';

type IdenticonProps<T extends IdenticonType> = HTMLAttributes<HTMLDivElement> & {
interface IdenticonProps<T extends IdenticonImgType> extends HTMLAttributes<HTMLDivElement> {
type: T;
hash: string;
size?: number;
options?: IdenticonOptions<T>;
};
options?: ImageIdenticonOptions<T>;
}

export const Identicon = <T extends IdenticonType>({
export const Identicon = <T extends IdenticonImgType>({
type,
hash,
size = 100,
Expand All @@ -21,19 +26,30 @@ export const Identicon = <T extends IdenticonType>({
options,
...rest
}: IdenticonProps<T>) => {
const backgroundImage = useMemo(() => getIdenticonUri(hash, size, type, options), [hash, options, size, type]);
const backgroundImage = useMemo(() => buildImageIdenticonUri(hash, size, type, options), [hash, options, size, type]);

return (
<div
className={clsx(
type === 'initials' ? 'bg-transparent' : 'bg-white',
'bg-no-repeat bg-center inline-block overflow-hidden',
'bg-white overflow-hidden',
'inline-block bg-no-repeat bg-center', // (!) Why?
className
)}
style={style}
style={{ width: size, height: size, ...style }}
{...rest}
>
<img src={backgroundImage} alt="" style={{ width: size, height: size }} />
<img src={backgroundImage} alt="" className="w-full h-full" />
</div>
);
};

interface IdenticonInitialsProps extends ImgHTMLAttributes<HTMLImageElement> {
value: string;
options?: InitialsIdenticonOptions;
}

export const IdenticonInitials: FC<IdenticonInitialsProps> = ({ value, options, ...props }) => {
const src = useMemo(() => buildInitialsIdenticonUri(value, options), [options, value]);

return <img src={src} {...props} />;
};
82 changes: 82 additions & 0 deletions src/app/atoms/InfiniteScroll.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import React, { CSSProperties, FC, ReactElement, useEffect, useMemo } from 'react';

import ReactInfiniteScrollComponent from 'react-infinite-scroll-component';

import { APP_CONTENT_PAPER_DOM_ID, SCROLL_DOCUMENT } from 'app/layouts/containers';

import { LoaderDebounce } from './LoaderDebounce';
import { SyncSpinner } from './SyncSpinner';

interface Props extends PropsWithChildren {
itemsLength: number;
isSyncing: boolean;
reachedTheEnd: boolean;
retryInitialLoad: EmptyFn;
loadMore: EmptyFn;
loader?: ReactElement;
}

export const InfiniteScroll: FC<Props> = ({
itemsLength,
isSyncing,
reachedTheEnd,
retryInitialLoad,
loadMore,
loader,
children
}) => {
const loadNext = itemsLength ? loadMore : retryInitialLoad;

/**
* Build onscroll listener to trigger next loading, when fetching data resulted in error.
* `InfiniteScroll.props.next` won't be triggered in this case.
*/
const onScroll = useMemo(() => {
if (isSyncing || reachedTheEnd) return;

return ({ target }: { target: EventTarget | null }) => {
const elem = (target instanceof Document ? target.scrollingElement! : target) as HTMLElement;

if (isScrollAtTheEnd(elem)) loadNext();
};
}, [loadNext, isSyncing, reachedTheEnd]);

const scrollableElem = useMemo(() => document.getElementById(APP_CONTENT_PAPER_DOM_ID), []);

// For when there are too few items to make initial scroll for loadMore:
useEffect(() => {
if (SCROLL_DOCUMENT || isSyncing || reachedTheEnd) return;

if (!scrollableElem || scrollableElem.scrollTop || scrollableElem.scrollHeight > scrollableElem.clientHeight)
return;

if (isScrollAtTheEnd(scrollableElem)) loadNext();
}, [isSyncing, itemsLength, reachedTheEnd]);

return (
<ReactInfiniteScrollComponent
dataLength={itemsLength}
hasMore={!reachedTheEnd}
next={loadNext}
onScroll={onScroll}
loader={null} // Doesn't always show this way
scrollableTarget={SCROLL_DOCUMENT ? undefined : APP_CONTENT_PAPER_DOM_ID}
style={STYLE}
>
{children}

<LoaderDebounce isSyncing={isSyncing} keepTime={2_000}>
{loader ?? <SyncSpinner className="mt-4" />}
</LoaderDebounce>
</ReactInfiniteScrollComponent>
);
};

const STYLE: CSSProperties = {
/** Scrollable element must be an ancestor of this component - document or other. */
overflow: 'unset'
};

function isScrollAtTheEnd(elem: Element) {
return elem.scrollHeight === elem.clientHeight + elem.scrollTop;
}
30 changes: 0 additions & 30 deletions src/app/atoms/Loader.tsx

This file was deleted.

Loading

0 comments on commit a3be6fe

Please sign in to comment.