Skip to content

Commit

Permalink
asset registry refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
Valentine1898 committed Apr 23, 2024
1 parent 56b4899 commit e78a11f
Show file tree
Hide file tree
Showing 16 changed files with 148 additions and 76 deletions.
9 changes: 7 additions & 2 deletions apps/minifront/src/components/ibc/ibc-out-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { InputBlock } from '../shared/input-block';
import { IbcLoaderResponse } from './ibc-loader';

export const IbcOutForm = () => {
const { balances } = useLoaderData() as IbcLoaderResponse;
const { balances, stakingTokenMetadata, registryAssets } = useLoaderData() as IbcLoaderResponse;
const {
sendIbcWithdraw,
destinationChainAddress,
Expand All @@ -20,7 +20,12 @@ export const IbcOutForm = () => {
setSelection,
chain,
} = useStore(ibcSelector);
const filteredBalances = filterBalancesPerChain(balances, chain);
const filteredBalances = filterBalancesPerChain(
balances,
chain,
stakingTokenMetadata,
registryAssets,
);
const validationErrors = useStore(ibcValidationErrors);

return (
Expand Down
21 changes: 17 additions & 4 deletions apps/minifront/src/components/send/send-form/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,15 @@ import InputToken from '../../shared/input-token';
import { useRefreshFee } from './use-refresh-fee';
import { GasFee } from '../../shared/gas-fee';
import { BalancesResponse } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/view/v1/view_pb';
import { Metadata } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/asset/v1/asset_pb';
import { getStakingTokenMetadata } from '../../../fetchers/registry';

export const SendAssetBalanceLoader: LoaderFunction = async (): Promise<BalancesResponse[]> => {
export interface SendLoaderResponse {
assetBalances: BalancesResponse[];
feeAssetMetadata: Metadata;
}

export const SendAssetBalanceLoader: LoaderFunction = async (): Promise<SendLoaderResponse> => {
await throwIfPraxNotConnectedTimeout();
const assetBalances = await getBalances();

Expand All @@ -23,12 +30,13 @@ export const SendAssetBalanceLoader: LoaderFunction = async (): Promise<Balances
state.send.selection = assetBalances[0];
});
}
const feeAssetMetadata = await getStakingTokenMetadata();

return assetBalances;
return { assetBalances, feeAssetMetadata };
};

export const SendForm = () => {
const assetBalances = useLoaderData() as BalancesResponse[];
const { assetBalances, feeAssetMetadata } = useLoaderData() as SendLoaderResponse;
const {
selection,
amount,
Expand Down Expand Up @@ -94,7 +102,12 @@ export const SendForm = () => {
balances={assetBalances}
/>

<GasFee fee={fee} feeTier={feeTier} setFeeTier={setFeeTier} />
<GasFee
fee={fee}
feeTier={feeTier}
feeAssetMetadata={feeAssetMetadata}
setFeeTier={setFeeTier}
/>

<InputBlock
label='Memo'
Expand Down
12 changes: 7 additions & 5 deletions apps/minifront/src/components/shared/gas-fee.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import {
SegmentedPickerOption,
} from '@penumbra-zone/ui/components/ui/segmented-picker';
import { InputBlock } from './input-block';
import { localAssets } from '@penumbra-zone/constants/src/assets';
import { ValueViewComponent } from '@penumbra-zone/ui/components/ui/tx/view/value';
import { ValueView } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/asset/v1/asset_pb';

const PENUMBRA_DENOM_METADATA = localAssets.find(asset => asset.display === 'penumbra')!;
import {
Metadata,
ValueView,
} from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/asset/v1/asset_pb';

const FEE_TIER_OPTIONS: SegmentedPickerOption<FeeTier_Tier>[] = [
{
Expand All @@ -31,18 +31,20 @@ const FEE_TIER_OPTIONS: SegmentedPickerOption<FeeTier_Tier>[] = [
export const GasFee = ({
fee,
feeTier,
feeAssetMetadata,
setFeeTier,
}: {
fee: Fee | undefined;
feeTier: FeeTier_Tier;
feeAssetMetadata: Metadata;
setFeeTier: (feeTier: FeeTier_Tier) => void;
}) => {
let feeValueView: ValueView | undefined;
if (fee?.amount)
feeValueView = new ValueView({
valueView: {
case: 'knownAssetId',
value: { amount: fee.amount, metadata: PENUMBRA_DENOM_METADATA },
value: { amount: fee.amount, metadata: feeAssetMetadata },
},
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
Metadata,
ValueView,
} from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/asset/v1/asset_pb';
import { STAKING_TOKEN_METADATA } from '@penumbra-zone/constants/src/assets';
import { ValidatorInfo } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/component/stake/v1/stake_pb';

const DELEGATION_TOKEN_METADATA = new Metadata({
Expand All @@ -29,6 +28,15 @@ const SOME_OTHER_TOKEN_METADATA = new Metadata({
symbol: 'SOT',
});

const STAKING_TOKEN_METADATA = new Metadata({
display: 'penumbra',
base: 'penumbra',
denomUnits: [{ denom: 'upenumbra' }, { denom: 'penumbra', exponent: 6 }],
name: 'penumbra',
penumbraAssetId: { inner: new Uint8Array([2, 5, 6, 7]) },
symbol: 'UM',
});

const validatorInfo = new ValidatorInfo({
validator: {
identityKey: {},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { ValueView } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/asset/v1/asset_pb';
import {
Metadata,
ValueView,
} from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/asset/v1/asset_pb';
import { ValidatorInfoComponent } from './validator-info-component';
import { ValueViewComponent } from '@penumbra-zone/ui/components/ui/tx/view/value';
import { StakingActions } from './staking-actions';
Expand All @@ -10,6 +13,7 @@ import {
getValidatorInfoFromValueView,
} from '@penumbra-zone/getters/src/value-view';
import { asValueView } from '@penumbra-zone/getters/src/equivalent-value';
import { useLoaderData } from 'react-router-dom';

/**
* Renders a `ValueView` that contains a delegation token, along with the
Expand Down Expand Up @@ -37,17 +41,19 @@ export const DelegationValueView = memo(
*/
unstakedTokens?: ValueView;
}) => {
const stakingTokenMetadata = useLoaderData() as Metadata;

Check failure on line 44 in apps/minifront/src/components/staking/account/delegation-value-view/index.tsx

View workflow job for this annotation

GitHub Actions / test

src/components/staking/account/delegation-value-view/index.test.tsx > <DelegationValueView /> > shows balance of the delegation token

Error: useLoaderData must be used within a data router. See https://reactrouter.com/routers/picking-a-router. ❯ Object.invariant [as UNSAFE_invariant] ../../node_modules/.pnpm/@remix-run+router@1.15.3/node_modules/@remix-run/router/history.ts:494:11 ❯ useDataRouterState ../../node_modules/.pnpm/react-router@6.22.3_react@18.2.0/node_modules/react-router/lib/hooks.tsx:858:3 ❯ Proxy.useLoaderData ../../node_modules/.pnpm/react-router@6.22.3_react@18.2.0/node_modules/react-router/lib/hooks.tsx:929:15 ❯ src/components/staking/account/delegation-value-view/index.tsx:44:34 ❯ renderWithHooks ../../node_modules/.pnpm/react-dom@18.2.0_react@18.2.0/node_modules/react-dom/cjs/react-dom.development.js:16305:18 ❯ updateFunctionComponent ../../node_modules/.pnpm/react-dom@18.2.0_react@18.2.0/node_modules/react-dom/cjs/react-dom.development.js:19588:20 ❯ updateSimpleMemoComponent ../../node_modules/.pnpm/react-dom@18.2.0_react@18.2.0/node_modules/react-dom/cjs/react-dom.development.js:19425:10 ❯ updateMemoComponent ../../node_modules/.pnpm/react-dom@18.2.0_react@18.2.0/node_modules/react-dom/cjs/react-dom.development.js:19284:14 ❯ beginWork ../../node_modules/.pnpm/react-dom@18.2.0_react@18.2.0/node_modules/react-dom/cjs/react-dom.development.js:21673:16 ❯ beginWork$1 ../../node_modules/.pnpm/react-dom@18.2.0_react@18.2.0/node_modules/react-dom/cjs/react-dom.development.js:27426:14

Check failure on line 44 in apps/minifront/src/components/staking/account/delegation-value-view/index.tsx

View workflow job for this annotation

GitHub Actions / test

src/components/staking/account/delegation-value-view/index.test.tsx > <DelegationValueView /> > shows the delegation token's equivalent value in terms of the staking token

Error: useLoaderData must be used within a data router. See https://reactrouter.com/routers/picking-a-router. ❯ Object.invariant [as UNSAFE_invariant] ../../node_modules/.pnpm/@remix-run+router@1.15.3/node_modules/@remix-run/router/history.ts:494:11 ❯ useDataRouterState ../../node_modules/.pnpm/react-router@6.22.3_react@18.2.0/node_modules/react-router/lib/hooks.tsx:858:3 ❯ Proxy.useLoaderData ../../node_modules/.pnpm/react-router@6.22.3_react@18.2.0/node_modules/react-router/lib/hooks.tsx:929:15 ❯ src/components/staking/account/delegation-value-view/index.tsx:44:34 ❯ renderWithHooks ../../node_modules/.pnpm/react-dom@18.2.0_react@18.2.0/node_modules/react-dom/cjs/react-dom.development.js:16305:18 ❯ updateFunctionComponent ../../node_modules/.pnpm/react-dom@18.2.0_react@18.2.0/node_modules/react-dom/cjs/react-dom.development.js:19588:20 ❯ updateSimpleMemoComponent ../../node_modules/.pnpm/react-dom@18.2.0_react@18.2.0/node_modules/react-dom/cjs/react-dom.development.js:19425:10 ❯ updateMemoComponent ../../node_modules/.pnpm/react-dom@18.2.0_react@18.2.0/node_modules/react-dom/cjs/react-dom.development.js:19284:14 ❯ beginWork ../../node_modules/.pnpm/react-dom@18.2.0_react@18.2.0/node_modules/react-dom/cjs/react-dom.development.js:21673:16 ❯ beginWork$1 ../../node_modules/.pnpm/react-dom@18.2.0_react@18.2.0/node_modules/react-dom/cjs/react-dom.development.js:27426:14
const validatorInfo = getValidatorInfoFromValueView(valueView);
const metadata = getMetadata(valueView);

const equivalentValueOfStakingToken = useMemo(() => {
const equivalentValue = getEquivalentValues(valueView).find(
equivalentValue => equivalentValue.numeraire?.display === STAKING_TOKEN,
equivalentValue =>
equivalentValue.numeraire?.penumbraAssetId === stakingTokenMetadata.penumbraAssetId,
);

if (equivalentValue) return asValueView(equivalentValue);
return undefined;
}, [valueView]);
}, [valueView, stakingTokenMetadata.penumbraAssetId]);

return (
<div className='flex flex-col gap-4 lg:flex-row lg:items-center lg:gap-8'>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { AllSlices } from '../../../../state';
import { UnbondingTokens } from './unbonding-tokens';
import { useStoreShallow } from '../../../../utils/use-store-shallow';
import { ZERO_BALANCE_UM } from './constants';
import { useLoaderData } from 'react-router-dom';
import { Metadata } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/asset/v1/asset_pb';

const headerSelector = (state: AllSlices) => ({
account: state.staking.account,
Expand All @@ -33,6 +35,7 @@ export const Header = () => {
const unstakedTokens = unstakedTokensByAccount.get(account);
const unbondingTokens = unbondingTokensByAccount.get(account);

const stakingTokenMetadata = useLoaderData() as Metadata;
return (
<Card gradient>
<CardContent>
Expand All @@ -49,6 +52,7 @@ export const Header = () => {
helpText='Total amount of UM you will receive, assuming no slashing, when you claim your unbonding tokens that are currently still in their unbonding period.'
tokens={unbondingTokens?.notYetClaimable.tokens}
total={unbondingTokens?.notYetClaimable.total}
stakingTokenMetadata={stakingTokenMetadata}
/>
</Stat>

Expand All @@ -57,6 +61,7 @@ export const Header = () => {
helpText='Total amount of UM you will receive, assuming no slashing, when you claim your unbonding tokens that are currently eligible for claiming.'
tokens={unbondingTokens?.claimable.tokens}
total={unbondingTokens?.claimable.total}
stakingTokenMetadata={stakingTokenMetadata}
>
{!!unbondingTokens?.claimable.tokens.length && (
<Button
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { ValueView } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/asset/v1/asset_pb';
import {
Metadata,
ValueView,
} from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/asset/v1/asset_pb';
import { getDisplayDenomFromView } from '@penumbra-zone/getters/src/value-view';
import {
TooltipProvider,
Expand All @@ -15,17 +18,19 @@ export const UnbondingTokens = ({
tokens,
helpText,
children,
stakingTokenMetadata,
}: {
total?: ValueView;
tokens?: ValueView[];
helpText: string;
children?: ReactNode;
stakingTokenMetadata: Metadata;
}) => {
return (
<TooltipProvider>
<Tooltip>
<TooltipTrigger>
<ValueViewComponent view={total ?? ZERO_BALANCE_UM} />
<ValueViewComponent view={total ?? ZERO_BALANCE_UM(stakingTokenMetadata)} />
</TooltipTrigger>
<TooltipContent>
<div className='flex flex-col gap-4'>
Expand Down
6 changes: 4 additions & 2 deletions apps/minifront/src/components/staking/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ import { Delegations } from './account/delegations';
import { LoaderFunction } from 'react-router-dom';
import { useStoreShallow } from '../../utils/use-store-shallow';
import { RestrictMaxWidth } from '../shared/restrict-max-width';
import { Metadata } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/asset/v1/asset_pb';
import { getStakingTokenMetadata } from '../../fetchers/registry';

export const StakingLoader: LoaderFunction = async () => {
export const StakingLoader: LoaderFunction = async (): Promise<Metadata> => {
await throwIfPraxNotConnectedTimeout();
// Await to avoid screen flicker.
await useStore.getState().staking.loadAndReduceBalances();

return null;
return await getStakingTokenMetadata();
};

const stakingLayoutSelector = (state: AllSlices) => ({
Expand Down
13 changes: 8 additions & 5 deletions apps/minifront/src/components/swap/asset-out-selector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ interface AssetOutSelectorProps {
filter?: (metadata: Metadata) => boolean;
}

const { registryAssets } = useLoaderData() as SwapLoaderResponse;
const sortedAssets = [...registryAssets].sort((a, b) => (a.symbol < b.symbol ? -1 : 1));

/**
* If the `filter` rejects the currently selected `assetOut`, switch to a
* different `assetOut`.
Expand All @@ -50,7 +47,10 @@ const switchAssetOutIfNecessary = ({
}
};

const useFilteredAssets = ({ assetOut, setAssetOut, filter }: AssetOutSelectorProps) => {
const useFilteredAssets = (
{ assetOut, setAssetOut, filter }: AssetOutSelectorProps,
sortedAssets: Metadata[],
) => {
const assets = filter ? sortedAssets.filter(filter) : sortedAssets;

useEffect(
Expand All @@ -63,7 +63,10 @@ const useFilteredAssets = ({ assetOut, setAssetOut, filter }: AssetOutSelectorPr

/** @todo Refactor to use `SelectTokenModal` */
export const AssetOutSelector = ({ setAssetOut, assetOut, filter }: AssetOutSelectorProps) => {
const assets = useFilteredAssets({ assetOut, setAssetOut, filter });
const { registryAssets } = useLoaderData() as SwapLoaderResponse;
const sortedAssets = [...registryAssets].sort((a, b) => (a.symbol < b.symbol ? -1 : 1));

const assets = useFilteredAssets({ assetOut, setAssetOut, filter }, sortedAssets);

return (
<Dialog>
Expand Down
2 changes: 1 addition & 1 deletion apps/minifront/src/components/swap/swap-loader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export const unclaimedSwapsWithMetadata = async (): Promise<UnclaimedSwapsWithMe
export const SwapLoader: LoaderFunction = async (): Promise<SwapLoaderResponse> => {
await throwIfPraxNotConnectedTimeout();

let registryAssets = await getAssetsFromRegistry();
const registryAssets = await getAssetsFromRegistry();

const [assetBalances, unclaimedSwaps] = await Promise.all([
getAndSetDefaultAssetBalances(registryAssets),
Expand Down
Loading

0 comments on commit e78a11f

Please sign in to comment.