Skip to content

Commit

Permalink
Claimables [PR #1]: updates to query, types, utils, wallet screen ren…
Browse files Browse the repository at this point in the history
…dering logic + wallet screen components (#6140)

* updates to query, types, & wallet screen components

* rm onPress

* thanks greg
  • Loading branch information
benisgold authored Sep 30, 2024
1 parent b1ba263 commit 8d84b7c
Show file tree
Hide file tree
Showing 10 changed files with 158 additions and 54 deletions.
9 changes: 7 additions & 2 deletions src/components/asset-list/RecyclerAssetList2/Claimable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@ import { useClaimables } from '@/resources/addys/claimables/query';
import { FasterImageView } from '@candlefinance/faster-image';
import { ButtonPressAnimation } from '@/components/animations';
import { deviceUtils } from '@/utils';
import Routes from '@/navigation/routesNames';
import { ExtendedState } from './core/RawRecyclerList';

export default function Claimable({ uniqueId }: { uniqueId: string }) {
export const Claimable = React.memo(function Claimable({ uniqueId, extendedState }: { uniqueId: string; extendedState: ExtendedState }) {
const { accountAddress, nativeCurrency } = useAccountSettings();
const { navigate } = extendedState;

const { data = [] } = useClaimables(
{
address: accountAddress,
Expand All @@ -25,6 +29,7 @@ export default function Claimable({ uniqueId }: { uniqueId: string }) {
return (
<Box
as={ButtonPressAnimation}
// onPress={() => navigate(Routes.CLAIM_CLAIMABLE_PANEL, { claimable })}
scaleTo={0.96}
paddingHorizontal="20px"
justifyContent="space-between"
Expand Down Expand Up @@ -68,4 +73,4 @@ export default function Claimable({ uniqueId }: { uniqueId: string }) {
</Box>
</Box>
);
}
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const AnimatedImgixImage = Animated.createAnimatedComponent(Image);
const TokenFamilyHeaderAnimationDuration = 200;
const TokenFamilyHeaderHeight = 48;

const ClaimablesListHeader = ({ total }: { total: string }) => {
export const ClaimablesListHeader = React.memo(function ClaimablesListHeader({ total }: { total: string }) {
const { colors } = useTheme();
const { isClaimablesOpen, toggleOpenClaimables } = useOpenClaimables();

Expand Down Expand Up @@ -84,10 +84,4 @@ const ClaimablesListHeader = ({ total }: { total: string }) => {
</Box>
</ButtonPressAnimation>
);
};

ClaimablesListHeader.animationDuration = TokenFamilyHeaderAnimationDuration;

ClaimablesListHeader.height = TokenFamilyHeaderHeight;

export default ClaimablesListHeader;
});
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ import { RemoteCardCarousel } from '@/components/cards/remote-cards';
import WrappedCollectiblesHeader from '../WrappedCollectiblesHeader';
import NFTLoadingSkeleton from '../NFTLoadingSkeleton';
import { NFTEmptyState } from '../NFTEmptyState';
import Claimable from '../Claimable';
import ClaimablesListHeader from '../ClaimablesListHeader';
import { ClaimablesListHeader } from '../ClaimablesListHeader';
import { Claimable } from '../Claimable';

function rowRenderer(type: CellType, { uid }: { uid: string }, _: unknown, extendedState: ExtendedState) {
const data = extendedState.additionalData[uid];
Expand Down Expand Up @@ -175,7 +175,7 @@ function rowRenderer(type: CellType, { uid }: { uid: string }, _: unknown, exten
case CellType.CLAIMABLE: {
const { uniqueId } = data as ClaimableExtraData;

return <Claimable uniqueId={uniqueId} />;
return <Claimable uniqueId={uniqueId} extendedState={extendedState} />;
}

case CellType.LOADING_ASSETS:
Expand Down
32 changes: 18 additions & 14 deletions src/helpers/buildWalletSections.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { createSelector } from 'reselect';
import { buildBriefCoinsList, buildBriefUniqueTokenList } from './assets';
import { NativeCurrencyKey, ParsedAddressAsset } from '@/entities';
import { queryClient } from '@/react-query';
import { positionsQueryKey } from '@/resources/defi/PositionsQuery';
import store from '@/redux/store';
import { ClaimableExtraData, PositionExtraData } from '@/components/asset-list/RecyclerAssetList2/core/ViewTypes';
import { DEFI_POSITIONS, CLAIMABLES, ExperimentalValue } from '@/config/experimental';
import { RainbowPositions } from '@/resources/defi/types';
import { claimablesQueryKey } from '@/resources/addys/claimables/query';
import { Claimable } from '@/resources/addys/claimables/types';
import { add, convertAmountToNativeDisplay } from './utilities';
import { RainbowConfig } from '@/model/remoteConfig';
Expand Down Expand Up @@ -60,20 +57,24 @@ const isFetchingNftsSelector = (state: any) => state.isFetchingNfts;
const listTypeSelector = (state: any) => state.listType;
const remoteConfigSelector = (state: any) => state.remoteConfig;
const experimentalConfigSelector = (state: any) => state.experimentalConfig;
const positionsSelector = (state: any) => state.positions;
const claimablesSelector = (state: any) => state.claimables;

const buildBriefWalletSections = (
balanceSectionData: any,
uniqueTokenFamiliesSection: any,
remoteConfig: RainbowConfig,
experimentalConfig: Record<string, ExperimentalValue>
experimentalConfig: Record<string, ExperimentalValue>,
positions: RainbowPositions | undefined,
claimables: Claimable[] | undefined
) => {
const { balanceSection, isEmpty, isLoadingUserAssets } = balanceSectionData;

const positionsEnabled = experimentalConfig[DEFI_POSITIONS] && !IS_TEST;
const claimablesEnabled = (remoteConfig.claimables || experimentalConfig[CLAIMABLES]) && !IS_TEST;

const positionSection = positionsEnabled ? withPositionsSection(isLoadingUserAssets) : [];
const claimablesSection = claimablesEnabled ? withClaimablesSection(isLoadingUserAssets) : [];
const positionSection = positionsEnabled ? withPositionsSection(positions, isLoadingUserAssets) : [];
const claimablesSection = claimablesEnabled ? withClaimablesSection(claimables, isLoadingUserAssets) : [];
const sections = [balanceSection, claimablesSection, positionSection, uniqueTokenFamiliesSection];

const filteredSections = sections.filter(section => section.length !== 0).flat(1);
Expand All @@ -84,10 +85,7 @@ const buildBriefWalletSections = (
};
};

const withPositionsSection = (isLoadingUserAssets: boolean) => {
const { accountAddress: address, nativeCurrency: currency } = store.getState().settings;
const positionsObj: RainbowPositions | undefined = queryClient.getQueryData(positionsQueryKey({ address, currency }));

const withPositionsSection = (positionsObj: RainbowPositions | undefined, isLoadingUserAssets: boolean) => {
const result: PositionExtraData[] = [];
const sortedPositions = positionsObj?.positions?.sort((a, b) => (a.totals.totals.amount > b.totals.totals.amount ? -1 : 1));
sortedPositions?.forEach((position, index) => {
Expand Down Expand Up @@ -118,9 +116,8 @@ const withPositionsSection = (isLoadingUserAssets: boolean) => {
return [];
};

const withClaimablesSection = (isLoadingUserAssets: boolean) => {
const { accountAddress: address, nativeCurrency: currency } = store.getState().settings;
const claimables: Claimable[] | undefined = queryClient.getQueryData(claimablesQueryKey({ address, currency }));
const withClaimablesSection = (claimables: Claimable[] | undefined, isLoadingUserAssets: boolean) => {
const { nativeCurrency: currency } = store.getState().settings;

const result: ClaimableExtraData[] = [];
let totalNativeValue = '0';
Expand Down Expand Up @@ -285,6 +282,13 @@ const briefBalanceSectionSelector = createSelector(
);

export const buildBriefWalletSectionsSelector = createSelector(
[briefBalanceSectionSelector, (state: any) => briefUniqueTokenDataSelector(state), remoteConfigSelector, experimentalConfigSelector],
[
briefBalanceSectionSelector,
(state: any) => briefUniqueTokenDataSelector(state),
remoteConfigSelector,
experimentalConfigSelector,
positionsSelector,
claimablesSelector,
],
buildBriefWalletSections
);
8 changes: 8 additions & 0 deletions src/hooks/useWalletSectionsData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import useNftSort from './useNFTsSortBy';
import useWalletsWithBalancesAndNames from './useWalletsWithBalancesAndNames';
import { useRemoteConfig } from '@/model/remoteConfig';
import { RainbowContext } from '@/helpers/RainbowContext';
import { usePositions } from '@/resources/defi/PositionsQuery';
import { useClaimables } from '@/resources/addys/claimables/query';

export default function useWalletSectionsData({
type,
Expand All @@ -35,6 +37,8 @@ export default function useWalletSectionsData({
address: accountAddress,
sortBy: nftSort,
});
const { data: positions } = usePositions({ address: accountAddress, currency: nativeCurrency });
const { data: claimables } = useClaimables({ address: accountAddress, currency: nativeCurrency });

const walletsWithBalancesAndNames = useWalletsWithBalancesAndNames();

Expand Down Expand Up @@ -76,6 +80,8 @@ export default function useWalletSectionsData({
nftSort,
remoteConfig,
experimentalConfig,
positions,
claimables,
};

const { briefSectionsData, isEmpty } = buildBriefWalletSectionsSelector(accountInfo);
Expand Down Expand Up @@ -110,6 +116,8 @@ export default function useWalletSectionsData({
nftSort,
remoteConfig,
experimentalConfig,
positions,
claimables,
]);
return walletSections;
}
8 changes: 5 additions & 3 deletions src/resources/addys/claimables/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ import { CLAIMABLES, useExperimentalFlag } from '@/config';
import { IS_TEST } from '@/env';
import { SUPPORTED_CHAIN_IDS } from '@/chains';

const addysHttp = new RainbowFetchClient({
baseURL: 'https://addys.p.rainbow.me/v3',
export const ADDYS_BASE_URL = 'https://addys.p.rainbow.me/v3';

export const addysHttp = new RainbowFetchClient({
baseURL: ADDYS_BASE_URL,
headers: {
Authorization: `Bearer ${ADDYS_API_KEY}`,
},
Expand All @@ -30,7 +32,7 @@ export type ClaimablesArgs = {
// Query Key

export const claimablesQueryKey = ({ address, currency }: ClaimablesArgs) =>
createQueryKey('claimables', { address, currency }, { persisterVersion: 1 });
createQueryKey('claimables', { address, currency }, { persisterVersion: 2 });

type ClaimablesQueryKey = ReturnType<typeof claimablesQueryKey>;

Expand Down
72 changes: 64 additions & 8 deletions src/resources/addys/claimables/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ChainId } from '@rainbow-me/swaps';
import { Address } from 'viem';
import { AddysAsset, AddysConsolidatedError, AddysResponseStatus } from '../types';
import { ChainId } from '@/chains/types';

interface Colors {
primary: string;
Expand Down Expand Up @@ -28,20 +28,33 @@ interface DApp {
colors: Colors;
}

type ClaimableType = 'transaction' | 'sponsored';

export interface AddysClaimable {
interface AddysBaseClaimable {
name: string;
unique_id: string;
type: ClaimableType;
type: string;
network: ChainId;
asset: AddysAsset;
amount: string;
dapp: DApp;
claim_action_type?: string | null;
}

interface AddysTransactionClaimable extends AddysBaseClaimable {
claim_action_type: 'transaction';
claim_action: ClaimActionTransaction[];
}

interface AddysSponsoredClaimable extends AddysBaseClaimable {
claim_action_type: 'sponsored';
claim_action: ClaimActionSponsored[];
}

interface AddysUnsupportedClaimable extends AddysBaseClaimable {
claim_action_type?: 'unknown' | null;
claim_action?: ClaimAction[];
}

export type AddysClaimable = AddysTransactionClaimable | AddysSponsoredClaimable | AddysUnsupportedClaimable;

interface ConsolidatedClaimablesPayloadResponse {
claimables: AddysClaimable[];
}
Expand All @@ -61,8 +74,13 @@ export interface ConsolidatedClaimablesResponse {
payload: ConsolidatedClaimablesPayloadResponse;
}

// will add more attributes as needed
export interface Claimable {
interface BaseClaimable {
asset: {
iconUrl: string;
name: string;
symbol: string;
};
chainId: ChainId;
name: string;
uniqueId: string;
iconUrl: string;
Expand All @@ -71,3 +89,41 @@ export interface Claimable {
nativeAsset: { amount: string; display: string };
};
}

export interface TransactionClaimable extends BaseClaimable {
type: 'transaction';
action: { to: Address; data: string };
}

export interface SponsoredClaimable extends BaseClaimable {
type: 'sponsored';
action: { url: string; method: string };
}

export type Claimable = TransactionClaimable | SponsoredClaimable;

interface ClaimTransactionStatus {
network: ChainId;
transaction_hash: string;
explorer_url: string;
sponsored_status: string;
}

interface ClaimPayloadResponse {
success: boolean;
claimable: Claimable | null;
claim_transaction_status: ClaimTransactionStatus | null;
}

interface ClaimMetadataResponse {
address: string;
chain_id: ChainId;
currency: string;
claim_type: string;
error: string;
}

export interface ClaimResponse {
metadata: ClaimMetadataResponse;
payload: ClaimPayloadResponse;
}
53 changes: 43 additions & 10 deletions src/resources/addys/claimables/utils.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,50 @@
import { NativeCurrencyKey } from '@/entities';
import { AddysClaimable, Claimable } from './types';
import { convertRawAmountToBalance, convertRawAmountToNativeDisplay, greaterThan, lessThan } from '@/helpers/utilities';
import { convertRawAmountToBalance, convertRawAmountToNativeDisplay, greaterThan } from '@/helpers/utilities';

export const parseClaimables = (claimables: AddysClaimable[], currency: NativeCurrencyKey): Claimable[] => {
return claimables
.map(claimable => ({
name: claimable.name,
uniqueId: claimable.unique_id,
iconUrl: claimable.dapp.icon_url,
value: {
claimAsset: convertRawAmountToBalance(claimable.amount, claimable.asset),
nativeAsset: convertRawAmountToNativeDisplay(claimable.amount, claimable.asset.decimals, claimable.asset.price.value, currency),
},
}))
.map(claimable => {
if (
!(claimable.claim_action_type === 'transaction' || claimable.claim_action_type === 'sponsored') ||
!claimable.claim_action?.length
) {
return undefined;
}

const baseClaimable = {
asset: {
iconUrl: claimable.asset.icon_url,
name: claimable.asset.name,
symbol: claimable.asset.symbol,
},
chainId: claimable.network,
name: claimable.name,
uniqueId: claimable.unique_id,
iconUrl: claimable.dapp.icon_url,
value: {
claimAsset: convertRawAmountToBalance(claimable.amount, claimable.asset),
nativeAsset: convertRawAmountToNativeDisplay(claimable.amount, claimable.asset.decimals, claimable.asset.price.value, currency),
},
};

if (claimable.claim_action_type === 'transaction') {
return {
...baseClaimable,
type: 'transaction' as const,
action: {
to: claimable.claim_action[0].address_to,
data: claimable.claim_action[0].calldata,
},
};
} else if (claimable.claim_action_type === 'sponsored') {
return {
...baseClaimable,
type: 'sponsored' as const,
action: { method: claimable.claim_action[0].method, url: claimable.claim_action[0].url },
};
}
})
.filter((c): c is Claimable => !!c)
.sort((a, b) => (greaterThan(a.value.claimAsset.amount ?? '0', b.value.claimAsset.amount ?? '0') ? -1 : 1));
};
8 changes: 7 additions & 1 deletion src/resources/defi/PositionsQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { ADDYS_API_KEY } from 'react-native-dotenv';
import { AddysPositionsResponse, PositionsArgs } from './types';
import { parsePositions } from './utils';
import { SUPPORTED_CHAIN_IDS } from '@/chains';
import { DEFI_POSITIONS, useExperimentalFlag } from '@/config';
import { IS_TEST } from '@/env';

export const buildPositionsUrl = (address: string) => {
const networkString = SUPPORTED_CHAIN_IDS.join(',');
Expand Down Expand Up @@ -77,5 +79,9 @@ export async function fetchPositions(
// Query Hook

export function usePositions({ address, currency }: PositionsArgs, config: QueryConfig<PositionsResult, Error, PositionsQueryKey> = {}) {
return useQuery(positionsQueryKey({ address, currency }), positionsQueryFunction, { ...config, enabled: !!address });
const positionsEnabled = useExperimentalFlag(DEFI_POSITIONS);
return useQuery(positionsQueryKey({ address, currency }), positionsQueryFunction, {
...config,
enabled: !!(address && positionsEnabled && !IS_TEST),
});
}
Loading

0 comments on commit 8d84b7c

Please sign in to comment.