Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use new registry [part 3] - assets registry #952

Merged
merged 23 commits into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
};

Comment on lines -14 to -22
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interaction with registry moved to fetchers/registry.ts

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();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing here — should pull from extension rather than GitHub


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
Loading