Skip to content

Commit

Permalink
Use BalancesResponses
Browse files Browse the repository at this point in the history
  • Loading branch information
jessepinho committed Jan 6, 2025
1 parent a89a968 commit 88ca28b
Show file tree
Hide file tree
Showing 13 changed files with 138 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,33 @@ import { useAppDispatch, useAppSelector } from '@/store/hooks';
import { setSelectedAssetSymbol } from '@/store/portfolioScreen';
import { Sx, Text, View } from 'dripsy';
import useTransactionsForAsset from './useTransactionsForAsset';
import { getBalanceView } from '@penumbra-zone/getters/balances-response';
import { getSymbolFromValueView } from '@penumbra-zone/getters/value-view';
import { BalancesResponse } from '@penumbra-zone/protobuf/penumbra/view/v1/view_pb';
import { createSelector } from 'reselect';
import { RootState } from '@/store';
import { getFormattedAmtFromValueView } from '@penumbra-zone/types/value-view';

const balanceSelector = (selectedAssetSymbol?: string) =>
createSelector(
[(state: RootState) => state.balances.balancesResponses, () => selectedAssetSymbol],
balancesResponses =>
balancesResponses.find(
balancesResponse =>
getBalanceView.pipe(getSymbolFromValueView)(new BalancesResponse(balancesResponse)) ===
selectedAssetSymbol,
),
);

/**
* An action sheet for a given asset, with a list of relevant transactions and
* buttons for actions related to the asset (such as sending).
*/
export default function AssetActionSheet() {
const selectedAssetSymbol = useAppSelector(state => state.portfolioScreen.selectedAssetSymbol);
const balance = useAppSelector(state =>
state.balances.balances.find(balance => balance.assetSymbol === selectedAssetSymbol),
const balancesResponse = useAppSelector(balanceSelector(selectedAssetSymbol));
const balanceView = getBalanceView.optional(
balancesResponse ? new BalancesResponse(balancesResponse) : undefined,
);
const dispatch = useAppDispatch();
const transactions = useTransactionsForAsset(selectedAssetSymbol);
Expand All @@ -28,11 +46,12 @@ export default function AssetActionSheet() {
<AssetIcon />
</View>

<Text sx={sx.balance}>
{balance?.amount} {balance?.assetSymbol}
</Text>

<Text sx={sx.equivalentValue}>{balance?.equivalentValue} USDC</Text>
{balanceView && (
<Text sx={sx.balance}>
{getFormattedAmtFromValueView(balanceView)}
{selectedAssetSymbol}
</Text>
)}
</View>

<TransactionList transactions={transactions} showTitle />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { Meta, StoryObj } from '@storybook/react';

import Balance from '.';
import balanceFactory from '@/factories/balance';
import balancesResponseFactory from '@/factories/balancesResponse';

const meta: Meta<typeof Balance> = {
component: Balance,
tags: ['autodocs'],
argTypes: {
balance: { control: false },
balancesResponse: { control: false },
},
};

export default meta;

export const Basic: StoryObj<typeof Balance> = {
args: {
balance: balanceFactory.build(),
balancesResponse: balancesResponseFactory.build(),
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,35 @@ import AssetIcon from '@/components/AssetIcon';
import ListItem from '@/components/ListItem';
import { useAppDispatch } from '@/store/hooks';
import { setSelectedAssetSymbol } from '@/store/portfolioScreen';
import IBalance from '@/types/Balance';
import { getBalanceView } from '@penumbra-zone/getters/balances-response';
import { getSymbolFromValueView, getDisplayDenomFromView } from '@penumbra-zone/getters/value-view';
import { getFormattedAmtFromValueView } from '@penumbra-zone/types/value-view';
import { BalancesResponse } from '@penumbra-zone/protobuf/penumbra/view/v1/view_pb';
import { Sx, Text, View } from 'dripsy';

export interface BalanceProps {
balance: IBalance;
balancesResponse: BalancesResponse;
}

export default function Balance({ balance }: BalanceProps) {
export default function Balance({ balancesResponse }: BalanceProps) {
const dispatch = useAppDispatch();
const balanceView = getBalanceView(balancesResponse);
const symbol = getSymbolFromValueView(balanceView);
const displayDenom = getDisplayDenomFromView(balanceView);
const formattedAmount = getFormattedAmtFromValueView(balanceView);

return (
<ListItem
avatar={<AssetIcon />}
primaryText={balance.assetSymbol}
secondaryText={balance.assetName}
primaryText={symbol}
secondaryText={displayDenom}
suffix={
<View sx={sx.suffix}>
<Text variant='small'>{balance.amount}</Text>
<Text sx={sx.equivalentValue}>{balance.equivalentValue} USDC</Text>
<Text variant='small'>{formattedAmount}</Text>
{/* <Text sx={sx.equivalentValue}>{balancesResponse.equivalentValue} USDC</Text> */}
</View>
}
onPress={() => dispatch(setSelectedAssetSymbol(balance.assetSymbol))}
onPress={() => dispatch(setSelectedAssetSymbol(symbol))}
/>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
import List from '@/components/List';
import IBalance from '@/types/Balance';
import { useLingui } from '@lingui/react/macro';
import Balance from './Balance';
import AssetActionSheet from './AssetActionSheet';
import { BalancesResponse } from '@penumbra-zone/protobuf/penumbra/view/v1/view_pb';
import { getSymbolFromValueView } from '@penumbra-zone/getters/value-view';

export interface BalanceListProps {
balances: IBalance[];
balancesResponses: BalancesResponse[];
}

/** Shows a list of the user's balances in every asset they hold. */
export default function BalanceList({ balances }: BalanceListProps) {
export default function BalanceList({ balancesResponses }: BalanceListProps) {
const { t } = useLingui();

return (
<>
<List title={t`Assets`}>
{balances.map(balance => (
<Balance key={balance.assetSymbol} balance={balance} />
{balancesResponses.map(balancesResponse => (
<Balance
key={getSymbolFromValueView(balancesResponse.balanceView)}
balancesResponse={balancesResponse}
/>
))}
</List>

Expand Down
20 changes: 14 additions & 6 deletions react-native-expo/components/PortfolioScreen/index.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
import { Sx, View } from 'dripsy';
import { ScrollView, Sx } from 'dripsy';
import BalanceAndActions from '../BalanceAndActions';
import BalanceList from './BalanceList';
import { useAppSelector } from '@/store/hooks';
import { createSelector } from 'reselect';
import { RootState } from '@/store';
import { BalancesResponse } from '@penumbra-zone/protobuf/penumbra/view/v1/view_pb';

const balancesResponsesSelector = createSelector(
[(state: RootState) => state.balances.balancesResponses],
balancesResponses =>
balancesResponses.map(balancesResponse => new BalancesResponse(balancesResponse)),
);

export default function PortfolioScreen() {
const balances = useAppSelector(state => state.balances.balances);
const balancesResponses = useAppSelector(balancesResponsesSelector);

return (
<View sx={sx.root}>
{/** @todo: Make this a `ScrollView`. */}
<ScrollView contentContainerSx={sx.root}>
<BalanceAndActions />

<BalanceList balances={balances} />
</View>
<BalanceList balancesResponses={balancesResponses} />
</ScrollView>
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,18 @@ const ALL_METADATAS = new ChainRegistryClient().bundled.get(PENUMBRA_CHAIN_ID).g
export default function useFilteredAssets() {
const searchText = useAppSelector(state => state.defaultPaymentTokenScreen.searchText);

const filteredAssets = useMemo(
() =>
ALL_METADATAS.filter(metadata => {
const searchTextLowerCase = searchText.toLocaleLowerCase();
const filteredAssets = useMemo(() => {
if (!searchText.trim().length) return ALL_METADATAS;

if (metadata.name.toLocaleLowerCase().includes(searchTextLowerCase)) return true;
if (metadata.symbol.toLocaleLowerCase().includes(searchTextLowerCase)) return true;
return ALL_METADATAS.filter(metadata => {
const searchTextLowerCase = searchText.toLocaleLowerCase();

return false;
}),
[searchText],
);
if (metadata.name.toLocaleLowerCase().includes(searchTextLowerCase)) return true;
if (metadata.symbol.toLocaleLowerCase().includes(searchTextLowerCase)) return true;

return false;
});
}, [searchText]);

return filteredAssets;
}
12 changes: 12 additions & 0 deletions react-native-expo/factories/amount.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import * as Factory from 'factory.ts';
import { PlainMessage } from '@bufbuild/protobuf';
import { Amount } from '@penumbra-zone/protobuf/penumbra/core/num/v1/num_pb';

const randomBigInt = () => BigInt(Math.round(Math.random() * 10 ** 7));

const amountFactory = Factory.makeFactory<PlainMessage<Amount>>({
hi: 0n,
lo: randomBigInt(),
});

export default amountFactory;
14 changes: 0 additions & 14 deletions react-native-expo/factories/balance.ts

This file was deleted.

23 changes: 23 additions & 0 deletions react-native-expo/factories/balancesResponse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import * as Factory from 'factory.ts';
import { BalancesResponse } from '@penumbra-zone/protobuf/penumbra/view/v1/view_pb';
import { ChainRegistryClient } from '@penumbra-labs/registry';
import { PENUMBRA_CHAIN_ID } from '@/utils/constants';
import { PlainMessage } from '@bufbuild/protobuf';
import amountFactory from './amount';

const METADATAS = new ChainRegistryClient().bundled.get(PENUMBRA_CHAIN_ID).getAllAssets();

const balancesResponseFactory = Factory.makeFactory<PlainMessage<BalancesResponse>>({
balanceView: Factory.each(i => ({
valueView: {
case: 'knownAssetId',
value: {
amount: amountFactory.build(),
equivalentValues: [],
metadata: METADATAS[i % METADATAS.length],
},
},
})),
});

export default balancesResponseFactory;
14 changes: 14 additions & 0 deletions react-native-expo/metro.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,20 @@ const ALIASES = {
* @todo: Fix this!
*/
'@penumbra-zone/bech32m/penumbra': '@penumbra-zone/bech32m/dist/penumbra',
/**
* Same issue here
*/
'@penumbra-zone/bech32m/passet': '@penumbra-zone/bech32m/dist/passet',
'@penumbra-zone/protobuf/penumbra/view/v1/view_pb':
'@penumbra-zone/protobuf/dist/gen/penumbra/view/v1/view_pb',
'@penumbra-zone/protobuf/penumbra/core/component/stake/v1/stake_pb':
'@penumbra-zone/protobuf/dist/gen/penumbra/core/component/stake/v1/stake_pb',
'@penumbra-zone/protobuf/penumbra/core/num/v1/num_pb':
'@penumbra-zone/protobuf/dist/gen/penumbra/core/num/v1/num_pb',
'@penumbra-zone/getters/metadata': '@penumbra-zone/getters/dist/metadata.js',
'@penumbra-zone/getters/value-view': '@penumbra-zone/getters/dist/value-view.js',
'@penumbra-zone/types/value-view': '@penumbra-zone/types/dist/value-view.js',
'@penumbra-zone/getters/balances-response': '@penumbra-zone/getters/dist/balances-response.js',
};

config.resolver.resolveRequest = (context, moduleName, platform) => {
Expand Down
3 changes: 2 additions & 1 deletion react-native-expo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@
"react-native-webview": "13.12.2",
"react-redux": "^9.2.0",
"redux-persist": "^6.0.0",
"redux-persist-expo-securestore": "^2.0.0"
"redux-persist-expo-securestore": "^2.0.0",
"reselect": "^5.1.1"
},
"devDependencies": {
"@babel/core": "^7.25.2",
Expand Down
15 changes: 9 additions & 6 deletions react-native-expo/store/balances.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import balanceFactory from '@/factories/balance';
import Balance from '@/types/Balance';
import { BalancesResponse } from '@penumbra-zone/protobuf/penumbra/view/v1/view_pb';
import balancesResponseFactory from '@/factories/balancesResponse';
import { createSlice } from '@reduxjs/toolkit';
import { PlainMessage } from '@bufbuild/protobuf';
import { ChainRegistryClient } from '@penumbra-labs/registry';
import { PENUMBRA_CHAIN_ID } from '@/utils/constants';

const METADATAS = new ChainRegistryClient().bundled.get(PENUMBRA_CHAIN_ID).getAllAssets();

export interface BalancesState {
balances: Balance[];
balancesResponses: PlainMessage<BalancesResponse>[];
}

const initialState: BalancesState = {
/** @todo: Populate with real data */
balances: balanceFactory.buildList(5),
balancesResponses: balancesResponseFactory.buildList(METADATAS.length),
};

export const balancesSlice = createSlice({
Expand All @@ -17,6 +22,4 @@ export const balancesSlice = createSlice({
reducers: {},
});

export const {} = balancesSlice.actions;

export default balancesSlice.reducer;
2 changes: 1 addition & 1 deletion react-native-expo/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9441,7 +9441,7 @@ requires-port@^1.0.0:
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==

reselect@^5.1.0:
reselect@^5.1.0, reselect@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/reselect/-/reselect-5.1.1.tgz#c766b1eb5d558291e5e550298adb0becc24bb72e"
integrity sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==
Expand Down

0 comments on commit 88ca28b

Please sign in to comment.