Skip to content

Commit

Permalink
Use new registry [part 3] - assets registry (#952)
Browse files Browse the repository at this point in the history
* rebase main

* use registry for storage and block processor

* wip: add assets registry for minifront

* wip

* bump @penumbra-labs/registry

* asset registry refactoring

* fix ui tests

* fix minifront tests

* refactor zero value view

* fix unbonding tests

* fix storage tests

* format

* rebase main

* Update apps/minifront/src/components/shared/asset-selector.tsx

Co-authored-by: Jesse Pinho <[email protected]>

* Update apps/minifront/src/components/staking/account/delegation-value-view/index.tsx

Co-authored-by: Jesse Pinho <[email protected]>

* Update apps/minifront/src/state/staking/index.ts

Co-authored-by: Jesse Pinho <[email protected]>

* revert Jesse reduce suggestion

* bump registry & use assets from indexed-db

* format

* move zero-value-view & bump registry

* wip

* remove equivalentValues

* rebase main

---------

Co-authored-by: Jesse Pinho <[email protected]>
  • Loading branch information
Valentine1898 and jessepinho authored Apr 26, 2024
1 parent 41bf56c commit 0dc3861
Show file tree
Hide file tree
Showing 36 changed files with 322 additions and 429 deletions.
28 changes: 15 additions & 13 deletions apps/minifront/src/components/ibc/ibc-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,32 @@ import { BalancesResponse } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumb
import { getBalances } from '../../fetchers/balances';
import { useStore } from '../../state';
import { filterBalancesPerChain } from '../../state/ibc';
import { getChainId } from '../../fetchers/chain-id';
import { Chain, ChainRegistryClient } from '@penumbra-labs/registry';
import { Chain } from '@penumbra-labs/registry';
import { Metadata } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/asset/v1/asset_pb';
import { getIbcConnections, getStakingTokenMetadata } from '../../fetchers/registry';
import { getAllAssets } from '../../fetchers/assets';

export interface IbcLoaderResponse {
balances: BalancesResponse[];
chains: Chain[];
stakingTokenMetadata: Metadata;
assets: Metadata[];
}

const getIbcConnections = async () => {
const chainId = await getChainId();
if (!chainId) throw new Error('Could not fetch chain id');

const registryClient = new ChainRegistryClient();
const { ibcConnections } = await registryClient.get(chainId);
return ibcConnections;
};

export const IbcLoader: LoaderFunction = async (): Promise<IbcLoaderResponse> => {
const assetBalances = await getBalances();
const ibcConnections = await getIbcConnections();
const stakingTokenMetadata = await getStakingTokenMetadata();
const assets = await getAllAssets();

if (assetBalances[0]) {
const initialChain = ibcConnections[0];
const initialSelection = filterBalancesPerChain(assetBalances, initialChain)[0];
const initialSelection = filterBalancesPerChain(
assetBalances,
initialChain,
stakingTokenMetadata,
assets,
)[0];

// set initial account if accounts exist and asset if account has asset list
useStore.setState(state => {
Expand All @@ -35,5 +37,5 @@ export const IbcLoader: LoaderFunction = async (): Promise<IbcLoaderResponse> =>
});
}

return { balances: assetBalances, chains: ibcConnections };
return { balances: assetBalances, chains: ibcConnections, stakingTokenMetadata, assets };
};
4 changes: 2 additions & 2 deletions apps/minifront/src/components/ibc/ibc-out/ibc-out-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { IbcLoaderResponse } from '../ibc-loader';
import { LockOpen2Icon } from '@radix-ui/react-icons';

export const IbcOutForm = () => {
const { balances } = useLoaderData() as IbcLoaderResponse;
const { balances, stakingTokenMetadata, assets } = useLoaderData() as IbcLoaderResponse;
const {
sendIbcWithdraw,
destinationChainAddress,
Expand All @@ -21,7 +21,7 @@ export const IbcOutForm = () => {
setSelection,
chain,
} = useStore(ibcSelector);
const filteredBalances = filterBalancesPerChain(balances, chain);
const filteredBalances = filterBalancesPerChain(balances, chain, stakingTokenMetadata, assets);
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
26 changes: 16 additions & 10 deletions apps/minifront/src/components/shared/asset-selector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import {
Metadata,
ValueView,
} from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/asset/v1/asset_pb';
import { localAssets } from '@penumbra-zone/constants/src/assets';
import { ValueViewComponent } from '@penumbra-zone/ui/components/ui/tx/view/value';
import { useEffect, useMemo, useState } from 'react';
import { IconInput } from '@penumbra-zone/ui/components/ui/icon-input';
import { MagnifyingGlassIcon } from '@radix-ui/react-icons';
import { SwapLoaderResponse } from '../swap/swap-loader';
import { useLoaderData } from 'react-router-dom';

interface AssetSelectorProps {
value?: Metadata;
Expand All @@ -27,10 +28,6 @@ interface AssetSelectorProps {
filter?: (metadata: Metadata) => boolean;
}

const sortedAssets = [...localAssets].sort((a, b) =>
a.symbol.toLocaleLowerCase() < b.symbol.toLocaleLowerCase() ? -1 : 1,
);

/**
* If the `filter` rejects the currently selected `asset`, switch to a different
* `asset`.
Expand All @@ -50,17 +47,26 @@ const switchAssetIfNecessary = ({
};

const useFilteredAssets = ({ value, onChange, filter }: AssetSelectorProps) => {
const { assets } = useLoaderData() as SwapLoaderResponse;
const sortedAssets = useMemo(
() =>
[...assets].sort((a, b) =>
a.symbol.toLocaleLowerCase() < b.symbol.toLocaleLowerCase() ? -1 : 1,
),
[assets],
);

const [search, setSearch] = useState('');

let assets = filter ? sortedAssets.filter(filter) : sortedAssets;
assets = search ? assets.filter(bySearch(search)) : assets;
let filteredAssets = filter ? sortedAssets.filter(filter) : sortedAssets;
filteredAssets = search ? assets.filter(bySearch(search)) : assets;

useEffect(
() => switchAssetIfNecessary({ value, onChange, filter, assets }),
[filter, value, assets, onChange],
() => switchAssetIfNecessary({ value, onChange, filter, assets: filteredAssets }),
[filter, value, filteredAssets, onChange],
);

return { assets, search, setSearch };
return { assets: filteredAssets, search, setSearch };
};

const bySearch = (search: string) => (asset: Metadata) =>
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';
import { bech32mIdentityKey } from '@penumbra-zone/bech32m/penumbravalid';

Expand Down Expand Up @@ -37,6 +36,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 Expand Up @@ -92,19 +100,25 @@ const valueView = new ValueView({

describe('<DelegationValueView />', () => {
it('shows balance of the delegation token', () => {
const { container } = render(<DelegationValueView valueView={valueView} />);
const { container } = render(
<DelegationValueView valueView={valueView} stakingTokenMetadata={STAKING_TOKEN_METADATA} />,
);

expect(container).toHaveTextContent('1delUM(abc...xyz)');
});

it("shows the delegation token's equivalent value in terms of the staking token", () => {
const { container } = render(<DelegationValueView valueView={valueView} />);
const { container } = render(
<DelegationValueView valueView={valueView} stakingTokenMetadata={STAKING_TOKEN_METADATA} />,
);

expect(container).toHaveTextContent('1.33UM');
});

it('does not show other equivalent values', () => {
const { container } = render(<DelegationValueView valueView={valueView} />);
const { container } = render(
<DelegationValueView valueView={valueView} stakingTokenMetadata={STAKING_TOKEN_METADATA} />,
);

expect(container).not.toHaveTextContent('2.66SOT');
});
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,7 +13,6 @@ import {
getValidatorInfoFromValueView,
} from '@penumbra-zone/getters/src/value-view';
import { asValueView } from '@penumbra-zone/getters/src/equivalent-value';
import { STAKING_TOKEN } from '@penumbra-zone/constants/src/assets';

/**
* Renders a `ValueView` that contains a delegation token, along with the
Expand All @@ -25,6 +27,7 @@ export const DelegationValueView = memo(
valueView,
votingPowerAsIntegerPercentage,
unstakedTokens,
stakingTokenMetadata,
}: {
/**
* A `ValueView` representing the address's balance of the given delegation
Expand All @@ -37,18 +40,19 @@ export const DelegationValueView = memo(
* Used to show the user how many tokens they have available to delegate.
*/
unstakedTokens?: ValueView;
stakingTokenMetadata: Metadata;
}) => {
const validatorInfo = getValidatorInfoFromValueView(valueView);
const metadata = getMetadata(valueView);

const equivalentValueOfStakingToken = useMemo(() => {
const equivalentValue = getEquivalentValues(valueView).find(
equivalentValue => equivalentValue.numeraire?.display === STAKING_TOKEN,
const equivalentValue = getEquivalentValues(valueView).find(equivalentValue =>
equivalentValue.numeraire?.penumbraAssetId?.equals(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
8 changes: 6 additions & 2 deletions apps/minifront/src/components/staking/account/delegations.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { AnimatePresence, motion } from 'framer-motion';
import { AllSlices } from '../../../state';
import { DelegationValueView } from './delegation-value-view';
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 { useStoreShallow } from '../../../utils/use-store-shallow';
import { getValidatorIdentityKeyFromValueView } from '@penumbra-zone/getters/src/value-view';
import { bech32mIdentityKey } from '@penumbra-zone/bech32m/penumbravalid';
Expand All @@ -19,7 +22,7 @@ const delegationsSelector = (state: AllSlices) => ({
votingPowerByValidatorInfo: state.staking.votingPowerByValidatorInfo,
});

export const Delegations = () => {
export const Delegations = ({ stakingTokenMetadata }: { stakingTokenMetadata: Metadata }) => {
const { delegations, unstakedTokens, votingPowerByValidatorInfo } =
useStoreShallow(delegationsSelector);

Expand All @@ -35,6 +38,7 @@ export const Delegations = () => {
<DelegationValueView
valueView={delegation}
unstakedTokens={unstakedTokens}
stakingTokenMetadata={stakingTokenMetadata}
votingPowerAsIntegerPercentage={getVotingPowerAsIntegerPercentage(
votingPowerByValidatorInfo,
delegation,
Expand Down
16 changes: 0 additions & 16 deletions apps/minifront/src/components/staking/account/header/constants.ts

This file was deleted.

Loading

0 comments on commit 0dc3861

Please sign in to comment.