fix(trading): party alias snags (#5947)
Co-authored-by: Dariusz Majcherczyk <dariusz.majcherczyk@gmail.com>
This commit is contained in:
parent
1d71a839b3
commit
1d721dc748
@ -170,6 +170,9 @@ const cacheConfig: InMemoryCacheConfig = {
|
|||||||
Fees: {
|
Fees: {
|
||||||
keyFields: false,
|
keyFields: false,
|
||||||
},
|
},
|
||||||
|
PartyProfile: {
|
||||||
|
keyFields: ['partyId'],
|
||||||
|
},
|
||||||
// The folling types are cached by the data provider and not by apollo
|
// The folling types are cached by the data provider and not by apollo
|
||||||
PositionUpdate: {
|
PositionUpdate: {
|
||||||
keyFields: false,
|
keyFields: false,
|
||||||
|
@ -8,6 +8,12 @@ import {
|
|||||||
mockConfig,
|
mockConfig,
|
||||||
MockedWalletProvider,
|
MockedWalletProvider,
|
||||||
} from '@vegaprotocol/wallet-react/testing';
|
} from '@vegaprotocol/wallet-react/testing';
|
||||||
|
import { MockedProvider, type MockedResponse } from '@apollo/react-testing';
|
||||||
|
import {
|
||||||
|
PartyProfilesDocument,
|
||||||
|
type PartyProfilesQuery,
|
||||||
|
type PartyProfilesQueryVariables,
|
||||||
|
} from '../vega-wallet-connect-button/__generated__/PartyProfiles';
|
||||||
|
|
||||||
jest.mock('@vegaprotocol/proposals', () => ({
|
jest.mock('@vegaprotocol/proposals', () => ({
|
||||||
ProtocolUpgradeCountdown: () => null,
|
ProtocolUpgradeCountdown: () => null,
|
||||||
@ -24,15 +30,45 @@ describe('Navbar', () => {
|
|||||||
publicKey: '2'.repeat(64),
|
publicKey: '2'.repeat(64),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
const key1Alias = 'key 1 alias';
|
||||||
const marketId = 'abc';
|
const marketId = 'abc';
|
||||||
const navbarContent = 'navbar-menu-content';
|
const navbarContent = 'navbar-menu-content';
|
||||||
|
|
||||||
|
const partyProfilesMock: MockedResponse<
|
||||||
|
PartyProfilesQuery,
|
||||||
|
PartyProfilesQueryVariables
|
||||||
|
> = {
|
||||||
|
request: {
|
||||||
|
query: PartyProfilesDocument,
|
||||||
|
variables: {
|
||||||
|
partyIds: mockKeys.map((k) => k.publicKey),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
result: {
|
||||||
|
data: {
|
||||||
|
partiesProfilesConnection: {
|
||||||
|
edges: [
|
||||||
|
{
|
||||||
|
node: {
|
||||||
|
partyId: mockKeys[0].publicKey,
|
||||||
|
alias: key1Alias,
|
||||||
|
metadata: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const renderComponent = (initialEntries?: string[]) => {
|
const renderComponent = (initialEntries?: string[]) => {
|
||||||
return render(
|
return render(
|
||||||
<MemoryRouter initialEntries={initialEntries}>
|
<MemoryRouter initialEntries={initialEntries}>
|
||||||
<MockedWalletProvider>
|
<MockedProvider mocks={[partyProfilesMock]}>
|
||||||
<Navbar />
|
<MockedWalletProvider>
|
||||||
</MockedWalletProvider>
|
<Navbar />
|
||||||
|
</MockedWalletProvider>
|
||||||
|
</MockedProvider>
|
||||||
</MemoryRouter>
|
</MemoryRouter>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -140,6 +176,7 @@ describe('Navbar', () => {
|
|||||||
const activeKey = within(menu.getByTestId(/key-1+-mobile/));
|
const activeKey = within(menu.getByTestId(/key-1+-mobile/));
|
||||||
expect(activeKey.getByText(mockKeys[0].name)).toBeInTheDocument();
|
expect(activeKey.getByText(mockKeys[0].name)).toBeInTheDocument();
|
||||||
expect(activeKey.getByTestId('icon-tick')).toBeInTheDocument();
|
expect(activeKey.getByTestId('icon-tick')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(key1Alias)).toBeInTheDocument();
|
||||||
|
|
||||||
const inactiveKey = within(menu.getByTestId(/key-2+-mobile/));
|
const inactiveKey = within(menu.getByTestId(/key-2+-mobile/));
|
||||||
await userEvent.click(inactiveKey.getByText(mockKeys[1].name));
|
await userEvent.click(inactiveKey.getByText(mockKeys[1].name));
|
||||||
|
@ -31,39 +31,27 @@ export const ProfileDialog = () => {
|
|||||||
const pubKey = useProfileDialogStore((store) => store.pubKey);
|
const pubKey = useProfileDialogStore((store) => store.pubKey);
|
||||||
const setOpen = useProfileDialogStore((store) => store.setOpen);
|
const setOpen = useProfileDialogStore((store) => store.setOpen);
|
||||||
|
|
||||||
const { send, status, error, reset } = useSimpleTransaction({
|
|
||||||
onSuccess: () => {
|
|
||||||
refetch();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const profileEdge = data?.partiesProfilesConnection?.edges.find(
|
const profileEdge = data?.partiesProfilesConnection?.edges.find(
|
||||||
(e) => e.node.partyId === pubKey
|
(e) => e.node.partyId === pubKey
|
||||||
);
|
);
|
||||||
|
|
||||||
const sendTx = (field: FormFields) => {
|
|
||||||
send({
|
|
||||||
updatePartyProfile: {
|
|
||||||
alias: field.alias,
|
|
||||||
metadata: [],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Dialog
|
||||||
open={open}
|
open={open}
|
||||||
onChange={() => {
|
onChange={() => {
|
||||||
setOpen(undefined);
|
setOpen(undefined);
|
||||||
reset();
|
|
||||||
}}
|
}}
|
||||||
title={t('Edit profile')}
|
title={t('Edit profile')}
|
||||||
>
|
>
|
||||||
<ProfileForm
|
<ProfileFormContainer
|
||||||
profile={profileEdge?.node}
|
profile={profileEdge?.node}
|
||||||
status={status}
|
onSuccess={() => {
|
||||||
error={error}
|
refetch();
|
||||||
onSubmit={sendTx}
|
|
||||||
|
setTimeout(() => {
|
||||||
|
setOpen(undefined);
|
||||||
|
}, 1000);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
@ -77,6 +65,32 @@ type Profile = NonNullable<
|
|||||||
PartyProfilesQuery['partiesProfilesConnection']
|
PartyProfilesQuery['partiesProfilesConnection']
|
||||||
>['edges'][number]['node'];
|
>['edges'][number]['node'];
|
||||||
|
|
||||||
|
const ProfileFormContainer = ({
|
||||||
|
profile,
|
||||||
|
onSuccess,
|
||||||
|
}: {
|
||||||
|
profile: Profile | undefined;
|
||||||
|
onSuccess: () => void;
|
||||||
|
}) => {
|
||||||
|
const { send, status, error } = useSimpleTransaction({ onSuccess });
|
||||||
|
const sendTx = (field: FormFields) => {
|
||||||
|
send({
|
||||||
|
updatePartyProfile: {
|
||||||
|
alias: field.alias,
|
||||||
|
metadata: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<ProfileForm
|
||||||
|
profile={profile}
|
||||||
|
status={status}
|
||||||
|
error={error}
|
||||||
|
onSubmit={sendTx}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const ProfileForm = ({
|
const ProfileForm = ({
|
||||||
profile,
|
profile,
|
||||||
onSubmit,
|
onSubmit,
|
||||||
@ -114,6 +128,14 @@ const ProfileForm = ({
|
|||||||
|
|
||||||
const errorMessage = errors.alias?.message || error;
|
const errorMessage = errors.alias?.message || error;
|
||||||
|
|
||||||
|
if (status === 'confirmed') {
|
||||||
|
return (
|
||||||
|
<p className="mt-2 mb-4 text-sm text-vega-green-600 dark:text-vega-green">
|
||||||
|
{t('Profile updated')}
|
||||||
|
</p>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit(onSubmit)} className="mt-3">
|
<form onSubmit={handleSubmit(onSubmit)} className="mt-3">
|
||||||
<FormGroup label="Alias" labelFor="alias">
|
<FormGroup label="Alias" labelFor="alias">
|
||||||
@ -131,12 +153,6 @@ const ProfileForm = ({
|
|||||||
</p>
|
</p>
|
||||||
</InputError>
|
</InputError>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{status === 'confirmed' && (
|
|
||||||
<p className="mt-2 mb-4 text-sm text-success">
|
|
||||||
{t('Profile updated')}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<TradingButton
|
<TradingButton
|
||||||
type="submit"
|
type="submit"
|
||||||
|
@ -94,6 +94,7 @@ export const VegaWalletConnectButton = ({
|
|||||||
<KeypairRadioGroup
|
<KeypairRadioGroup
|
||||||
pubKey={pubKey}
|
pubKey={pubKey}
|
||||||
pubKeys={pubKeys}
|
pubKeys={pubKeys}
|
||||||
|
activeKey={activeKey?.publicKey}
|
||||||
onSelect={selectPubKey}
|
onSelect={selectPubKey}
|
||||||
/>
|
/>
|
||||||
<TradingDropdownSeparator />
|
<TradingDropdownSeparator />
|
||||||
@ -138,15 +139,18 @@ export const VegaWalletConnectButton = ({
|
|||||||
const KeypairRadioGroup = ({
|
const KeypairRadioGroup = ({
|
||||||
pubKey,
|
pubKey,
|
||||||
pubKeys,
|
pubKeys,
|
||||||
|
activeKey,
|
||||||
onSelect,
|
onSelect,
|
||||||
}: {
|
}: {
|
||||||
pubKey: string | undefined;
|
pubKey: string | undefined;
|
||||||
pubKeys: Key[];
|
pubKeys: Key[];
|
||||||
|
activeKey: string | undefined;
|
||||||
onSelect: (pubKey: string) => void;
|
onSelect: (pubKey: string) => void;
|
||||||
}) => {
|
}) => {
|
||||||
const { data } = usePartyProfilesQuery({
|
const { data } = usePartyProfilesQuery({
|
||||||
variables: { partyIds: pubKeys.map((pk) => pk.publicKey) },
|
variables: { partyIds: pubKeys.map((pk) => pk.publicKey) },
|
||||||
skip: pubKeys.length <= 0,
|
skip: pubKeys.length <= 0,
|
||||||
|
fetchPolicy: 'cache-and-network',
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -156,14 +160,27 @@ const KeypairRadioGroup = ({
|
|||||||
(e) => e.node.partyId === pk.publicKey
|
(e) => e.node.partyId === pk.publicKey
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<KeypairItem key={pk.publicKey} pk={pk} alias={profile?.node.alias} />
|
<KeypairItem
|
||||||
|
key={pk.publicKey}
|
||||||
|
pk={pk}
|
||||||
|
isActive={activeKey === pk.publicKey}
|
||||||
|
alias={profile?.node.alias}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</TradingDropdownRadioGroup>
|
</TradingDropdownRadioGroup>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const KeypairItem = ({ pk, alias }: { pk: Key; alias: string | undefined }) => {
|
const KeypairItem = ({
|
||||||
|
pk,
|
||||||
|
isActive,
|
||||||
|
alias,
|
||||||
|
}: {
|
||||||
|
pk: Key;
|
||||||
|
alias: string | undefined;
|
||||||
|
isActive: boolean;
|
||||||
|
}) => {
|
||||||
const t = useT();
|
const t = useT();
|
||||||
const [copied, setCopied] = useCopyTimeout();
|
const [copied, setCopied] = useCopyTimeout();
|
||||||
const setOpen = useProfileDialogStore((store) => store.setOpen);
|
const setOpen = useProfileDialogStore((store) => store.setOpen);
|
||||||
@ -194,8 +211,13 @@ const KeypairItem = ({ pk, alias }: { pk: Key; alias: string | undefined }) => {
|
|||||||
data-testid={`key-${pk.publicKey}`}
|
data-testid={`key-${pk.publicKey}`}
|
||||||
>
|
>
|
||||||
<Tooltip description={t('Public facing key alias. Click to edit')}>
|
<Tooltip description={t('Public facing key alias. Click to edit')}>
|
||||||
<button data-testid="alias" onClick={() => setOpen(pk.publicKey)}>
|
<button
|
||||||
|
data-testid="alias"
|
||||||
|
onClick={() => setOpen(pk.publicKey)}
|
||||||
|
className="flex items-center gap-1"
|
||||||
|
>
|
||||||
{alias ? alias : t('No alias')}
|
{alias ? alias : t('No alias')}
|
||||||
|
{isActive && <VegaIcon name={VegaIconNames.EDIT} />}
|
||||||
</button>
|
</button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
@ -12,6 +12,8 @@ import CopyToClipboard from 'react-copy-to-clipboard';
|
|||||||
import { ViewType, useSidebar } from '../sidebar';
|
import { ViewType, useSidebar } from '../sidebar';
|
||||||
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
|
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
|
||||||
import { useT } from '../../lib/use-t';
|
import { useT } from '../../lib/use-t';
|
||||||
|
import { usePartyProfilesQuery } from '../vega-wallet-connect-button/__generated__/PartyProfiles';
|
||||||
|
import { useProfileDialogStore } from '../../stores/profile-dialog-store';
|
||||||
|
|
||||||
export const VegaWalletMenu = ({
|
export const VegaWalletMenu = ({
|
||||||
setMenu,
|
setMenu,
|
||||||
@ -23,6 +25,12 @@ export const VegaWalletMenu = ({
|
|||||||
const currentRouteId = useGetCurrentRouteId();
|
const currentRouteId = useGetCurrentRouteId();
|
||||||
const setViews = useSidebar((store) => store.setViews);
|
const setViews = useSidebar((store) => store.setViews);
|
||||||
|
|
||||||
|
const { data } = usePartyProfilesQuery({
|
||||||
|
variables: { partyIds: pubKeys.map((pk) => pk.publicKey) },
|
||||||
|
skip: pubKeys.length <= 0,
|
||||||
|
fetchPolicy: 'cache-and-network',
|
||||||
|
});
|
||||||
|
|
||||||
const activeKey = useMemo(() => {
|
const activeKey = useMemo(() => {
|
||||||
return pubKeys?.find((pk) => pk.publicKey === pubKey);
|
return pubKeys?.find((pk) => pk.publicKey === pubKey);
|
||||||
}, [pubKey, pubKeys]);
|
}, [pubKey, pubKeys]);
|
||||||
@ -37,14 +45,21 @@ export const VegaWalletMenu = ({
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="grow my-4" role="list">
|
<div className="grow my-4" role="list">
|
||||||
{(pubKeys || []).map((pk) => (
|
{(pubKeys || []).map((pk) => {
|
||||||
<KeypairListItem
|
const profile = data?.partiesProfilesConnection?.edges.find(
|
||||||
key={pk.publicKey}
|
(e) => e.node.partyId === pk.publicKey
|
||||||
pk={pk}
|
);
|
||||||
isActive={activeKey?.publicKey === pk.publicKey}
|
return (
|
||||||
onSelectItem={onSelectItem}
|
<KeypairListItem
|
||||||
/>
|
key={pk.publicKey}
|
||||||
))}
|
pk={pk}
|
||||||
|
isActive={activeKey?.publicKey === pk.publicKey}
|
||||||
|
onSelectItem={onSelectItem}
|
||||||
|
alias={profile?.node.alias}
|
||||||
|
setMenu={setMenu}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col gap-2 m-4">
|
<div className="flex flex-col gap-2 m-4">
|
||||||
@ -72,18 +87,23 @@ export const VegaWalletMenu = ({
|
|||||||
const KeypairListItem = ({
|
const KeypairListItem = ({
|
||||||
pk,
|
pk,
|
||||||
isActive,
|
isActive,
|
||||||
|
alias,
|
||||||
onSelectItem,
|
onSelectItem,
|
||||||
|
setMenu,
|
||||||
}: {
|
}: {
|
||||||
pk: Key;
|
pk: Key;
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
|
alias: string | undefined;
|
||||||
onSelectItem: (pk: string) => void;
|
onSelectItem: (pk: string) => void;
|
||||||
|
setMenu: (open: 'nav' | 'wallet' | null) => void;
|
||||||
}) => {
|
}) => {
|
||||||
const t = useT();
|
const t = useT();
|
||||||
const [copied, setCopied] = useCopyTimeout();
|
const [copied, setCopied] = useCopyTimeout();
|
||||||
|
const setOpen = useProfileDialogStore((store) => store.setOpen);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="flex flex-col w-full ml-4 mr-2 mb-4"
|
className="flex flex-col w-full px-4 mb-4"
|
||||||
data-testid={`key-${pk.publicKey}-mobile`}
|
data-testid={`key-${pk.publicKey}-mobile`}
|
||||||
>
|
>
|
||||||
<span className="flex gap-2 items-center mr-2">
|
<span className="flex gap-2 items-center mr-2">
|
||||||
@ -106,6 +126,24 @@ const KeypairListItem = ({
|
|||||||
</CopyToClipboard>
|
</CopyToClipboard>
|
||||||
{copied && <span className="text-xs">{t('Copied')}</span>}
|
{copied && <span className="text-xs">{t('Copied')}</span>}
|
||||||
</span>
|
</span>
|
||||||
|
<span
|
||||||
|
className="flex gap-2 items-center"
|
||||||
|
data-testid={`key-${pk.publicKey}`}
|
||||||
|
>
|
||||||
|
<span className="truncate">{alias ? alias : t('No alias')}</span>
|
||||||
|
{isActive && (
|
||||||
|
<button
|
||||||
|
data-testid="alias"
|
||||||
|
onClick={() => {
|
||||||
|
setOpen(pk.publicKey);
|
||||||
|
setMenu(null);
|
||||||
|
}}
|
||||||
|
className="flex items-center gap-1"
|
||||||
|
>
|
||||||
|
<VegaIcon name={VegaIconNames.EDIT} />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -186,7 +186,7 @@ def test_reward_history(
|
|||||||
|
|
||||||
def test_staking_reward(
|
def test_staking_reward(
|
||||||
setup_environment: Tuple[Page, str, str],
|
setup_environment: Tuple[Page, str, str],
|
||||||
) -> None:
|
):
|
||||||
page, tDAI_market, tDAI_asset_id = setup_environment
|
page, tDAI_market, tDAI_asset_id = setup_environment
|
||||||
expect(page.get_by_test_id("active-rewards-card")).to_have_count(2)
|
expect(page.get_by_test_id("active-rewards-card")).to_have_count(2)
|
||||||
staking_reward_card = page.get_by_test_id("active-rewards-card").nth(1)
|
staking_reward_card = page.get_by_test_id("active-rewards-card").nth(1)
|
||||||
|
Loading…
Reference in New Issue
Block a user