Compare commits

..
21 changed files with 213 additions and 508 deletions
@@ -1,8 +1,4 @@
import {
VegaConnectDialog,
VegaManageDialog,
ViewAsDialog,
} from '@vegaprotocol/wallet';
import { VegaConnectDialog, VegaManageDialog } from '@vegaprotocol/wallet';
import {
AppStateActionType,
useAppState,
@@ -29,8 +25,6 @@ export const VegaWalletDialogs = () => {
})
}
/>
<ViewAsDialog connector={Connectors.view} />
</>
);
};
@@ -0,0 +1,17 @@
import { Link } from '@vegaprotocol/ui-toolkit';
import { useTranslation } from 'react-i18next';
import { ExternalLinks } from '@vegaprotocol/environment';
export const DownloadWalletPrompt = () => {
const { t } = useTranslation();
return (
<>
<h3 className="mt-4 mb-2">{t('getWallet')}</h3>
<p>
<Link className="text-neutral-500" href={ExternalLinks.VEGA_WALLET_URL}>
{t('getWalletLink')}
</Link>
</p>
</>
);
};
@@ -1,25 +0,0 @@
import { ButtonLink, Link } from '@vegaprotocol/ui-toolkit';
import { useTranslation } from 'react-i18next';
import { ExternalLinks } from '@vegaprotocol/environment';
import { useViewAsDialog } from '@vegaprotocol/wallet';
export const VegaWalletPrompt = () => {
const { t } = useTranslation();
const setViewAsDialog = useViewAsDialog((state) => state.setOpen);
return (
<>
<h3 className="mt-4 mb-2">{t('getWallet')}</h3>
<div className="flex flex-row gap-4">
<Link className="text-neutral-500" href={ExternalLinks.VEGA_WALLET_URL}>
{t('getWalletLink')}
</Link>
<ButtonLink
className="text-neutral-500"
onClick={() => setViewAsDialog(true)}
>
{t('viewAsParty')}
</ButtonLink>
</div>
</>
);
};
@@ -20,7 +20,7 @@ import {
WalletCardHeader,
WalletCardRow,
} from '../wallet-card';
import { VegaWalletPrompt } from './vega-wallet-prompt';
import { DownloadWalletPrompt } from './download-wallet-prompt';
import { usePollForDelegations } from './hooks';
import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet';
import { Button, ButtonLink } from '@vegaprotocol/ui-toolkit';
@@ -85,7 +85,7 @@ const VegaWalletNotConnected = () => {
>
{t('connectVegaWalletToUseAssociated')}
</Button>
<VegaWalletPrompt />
<DownloadWalletPrompt />
</>
);
};
@@ -855,6 +855,5 @@
"Estimated time to upgrade": "Estimated time to upgrade",
"Upgraded at": "Upgraded at",
"dataIsIdentical": "Data is identical",
"updatesToMarket": "Updates to market",
"viewAsParty": "View as party"
"updatesToMarket": "Updates to market"
}
+1
View File
@@ -26,6 +26,7 @@ module.exports = defineConfig({
requestTimeout: 20000,
retries: 1,
testIsolation: false,
experimentalMemoryManagement: true,
},
env: {
ETHERSCAN_URL: 'https://sepolia.etherscan.io',
@@ -104,11 +104,11 @@ describe('deposit actions', { tags: '@smoke' }, () => {
cy.visit('/#/markets/market-1');
});
it('Deposit to trade is visible', () => {
it('Deposit to trade is visble', () => {
cy.getByTestId('Collateral').click();
cy.get('[row-id="asset-id"]').contains('tEURO').should('be.visible');
cy.contains('[data-testid="deposit"]', 'Deposit').should('be.visible');
cy.contains('[data-testid="deposit"]', 'Deposit').click();
cy.contains('[data-testid="deposit"]', 'Deposit')
.should('be.visible')
.click();
cy.getByTestId('deposit-submit').should('be.visible');
});
});
@@ -291,11 +291,9 @@ describe('positions', { tags: '@regression', testIsolation: true }, () => {
it('View settlement asset', () => {
visitAndClickPositions();
cy.get('[col-id="asset"]')
.eq(3)
.within(() => {
cy.get('button[type="button"]').click();
});
cy.get('[col-id="asset"]').within(() => {
cy.get('button[type="button"]').first().click();
});
// 7004-POSI-008
cy.getByTestId(dialogContent).should('be.visible');
cy.getByTestId(dialogCloseX).click();
@@ -12,108 +12,100 @@ const walletTransfer = 'wallet-transfer';
const ASSET_SEPOLIA_TBTC = 2;
describe.skip(
'transfer fees',
{ tags: '@regression', testIsolation: true },
() => {
beforeEach(() => {
cy.mockWeb3Provider();
cy.mockTradingPage();
cy.mockSubscription();
cy.setVegaWallet();
describe('transfer fees', { tags: '@regression', testIsolation: true }, () => {
beforeEach(() => {
cy.mockWeb3Provider();
cy.mockTradingPage();
cy.mockSubscription();
cy.setVegaWallet();
cy.visit('/');
cy.getByTestId(manageVegaWallet).click();
cy.getByTestId(walletTransfer).click();
cy.visit('/');
cy.getByTestId(manageVegaWallet).click();
cy.getByTestId(walletTransfer).click();
cy.wait('@Assets');
cy.wait('@Accounts');
cy.wait('@Assets');
cy.wait('@Accounts');
cy.mockVegaWalletTransaction();
});
cy.mockVegaWalletTransaction();
});
it('transfer fees tooltips', () => {
// 1003-TRAN-015
// 1003-TRAN-016
// 1003-TRAN-017
// 1003-TRAN-018
// 1003-TRAN-019
cy.getByTestId(transferForm);
cy.contains('Enter manually').click();
cy.getByTestId(transferForm)
.find(toAddressField)
.type(
'7f9cf07d3a9905b1a61a1069f7a758855da428bc0f4a97de87f48644bfc25535'
);
selectAsset(ASSET_SEPOLIA_TBTC);
cy.getByTestId(transferForm)
.find(amountField)
.type('1', { delay: 100, force: true });
it('transfer fees tooltips', () => {
// 1003-TRAN-015
// 1003-TRAN-016
// 1003-TRAN-017
// 1003-TRAN-018
// 1003-TRAN-019
cy.getByTestId(transferForm);
cy.contains('Enter manually').click();
cy.getByTestId(transferForm)
.find(toAddressField)
.type('7f9cf07d3a9905b1a61a1069f7a758855da428bc0f4a97de87f48644bfc25535');
selectAsset(ASSET_SEPOLIA_TBTC);
cy.getByTestId(transferForm)
.find(amountField)
.type('1', { delay: 100, force: true });
/// Check Include Transfer Fee tooltip
cy.get('label[for="include-transfer-fee"] div').realHover();
cy.get('[data-side="bottom"] div')
.should('be.visible')
.should('not.be.empty');
/// Check Include Transfer Fee tooltip
cy.get('label[for="include-transfer-fee"] div').realHover();
cy.get('[data-side="bottom"] div')
.should('be.visible')
.should('not.be.empty');
//Check Transfer Fee tooltip
cy.contains('div', 'Transfer fee').realHover();
cy.get('[data-side="bottom"] div')
.should('be.visible')
.should('not.be.empty');
//Check Transfer Fee tooltip
cy.contains('div', 'Transfer fee').realHover();
cy.get('[data-side="bottom"] div')
.should('be.visible')
.should('not.be.empty');
//Check Amount to be transferred tooltip
cy.contains('div', 'Amount to be transferred').realHover();
cy.get('[data-side="bottom"] div')
.should('be.visible')
.should('not.be.empty');
//Check Amount to be transferred tooltip
cy.contains('div', 'Amount to be transferred').realHover();
cy.get('[data-side="bottom"] div')
.should('be.visible')
.should('not.be.empty');
//Check Total amount (with fee) tooltip
cy.contains('div', 'Total amount (with fee)').realHover();
cy.get('[data-side="bottom"] div')
.should('be.visible')
.should('not.be.empty');
});
//Check Total amount (with fee) tooltip
cy.contains('div', 'Total amount (with fee)').realHover();
cy.get('[data-side="bottom"] div')
.should('be.visible')
.should('not.be.empty');
});
it('transfer fees', () => {
// 1003-TRAN-020
// 1003-TRAN-021
// 1003-TRAN-022
// 1003-TRAN-023
cy.getByTestId(transferForm);
cy.contains('Enter manually').click();
it('transfer fees', () => {
// 1003-TRAN-020
// 1003-TRAN-021
// 1003-TRAN-022
// 1003-TRAN-023
cy.getByTestId(transferForm);
cy.contains('Enter manually').click();
cy.getByTestId(transferForm)
.find(toAddressField)
.type(
'7f9cf07d3a9905b1a61a1069f7a758855da428bc0f4a97de87f48644bfc25535'
);
selectAsset(ASSET_SEPOLIA_TBTC);
cy.getByTestId(includeTransferFeeRadioBtn).should('be.disabled');
cy.getByTestId(transferForm)
.find(toAddressField)
.type('7f9cf07d3a9905b1a61a1069f7a758855da428bc0f4a97de87f48644bfc25535');
selectAsset(ASSET_SEPOLIA_TBTC);
cy.getByTestId(includeTransferFeeRadioBtn).should('be.disabled');
cy.getByTestId(transferForm)
.find(amountField)
.type('1', { delay: 100, force: true });
cy.getByTestId(transferForm)
.find(amountField)
.type('1', { delay: 100, force: true });
cy.getByTestId(transferFee)
.should('be.visible')
.should('contain.text', '0.01');
cy.getByTestId(transferAmount)
.should('be.visible')
.should('contain.text', '1.00');
cy.getByTestId(totalTransferfee)
.should('be.visible')
.should('contain.text', '1.01');
cy.getByTestId(includeTransferFeeRadioBtn).click();
cy.getByTestId(transferFee)
.should('be.visible')
.should('contain.text', '0.01');
cy.getByTestId(transferAmount)
.should('be.visible')
.should('contain.text', '0.99');
cy.getByTestId(totalTransferfee)
.should('be.visible')
.should('contain.text', '1.00');
});
}
);
cy.getByTestId(transferFee)
.should('be.visible')
.should('contain.text', '0.01');
cy.getByTestId(transferAmount)
.should('be.visible')
.should('contain.text', '1.00');
cy.getByTestId(totalTransferfee)
.should('be.visible')
.should('contain.text', '1.01');
cy.getByTestId(includeTransferFeeRadioBtn).click();
cy.getByTestId(transferFee)
.should('be.visible')
.should('contain.text', '0.01');
cy.getByTestId(transferAmount)
.should('be.visible')
.should('contain.text', '0.99');
cy.getByTestId(totalTransferfee)
.should('be.visible')
.should('contain.text', '1.00');
});
});
+1 -1
View File
@@ -7,7 +7,7 @@ module.exports = {
'scope-enum': async (ctx) => [
2,
'always',
['ci', 'docs', 'specs', ...(await utils.getProjects(ctx))],
['ci', 'docs', ...(await utils.getProjects(ctx))],
],
},
};
@@ -150,9 +150,3 @@ query StopOrders($partyId: ID!) {
}
}
}
query StopOrderById($stopOrderId: ID!) {
stopOrder(id: $stopOrderId) {
...StopOrderFields
}
}
@@ -32,7 +32,7 @@ export type OrdersUpdateSubscriptionVariables = Types.Exact<{
export type OrdersUpdateSubscription = { __typename?: 'Subscription', orders?: Array<{ __typename?: 'OrderUpdate', id: string, marketId: string, type?: Types.OrderType | null, side: Types.Side, size: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, price: string, timeInForce: Types.OrderTimeInForce, remaining: string, expiresAt?: any | null, createdAt: any, updatedAt?: any | null, liquidityProvisionId?: string | null, peggedOrder?: { __typename: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null, icebergOrder?: { __typename: 'IcebergOrder', peakSize: string, minimumVisibleSize: string, reservedRemaining: string } | null }> | null };
export type OrderSubmissionFieldsFragment = { __typename?: 'OrderSubmission', marketId: string, price: string, size: string, side: Types.Side, timeInForce: Types.OrderTimeInForce, expiresAt: any, type: Types.OrderType, reference?: string | null, postOnly?: boolean | null, reduceOnly?: boolean | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null };
export type OrderSubmissionFieldsFragment = { __typename?: 'OrderSubmission', marketId: string, price: string, size: string, side: Types.Side, timeInForce: Types.OrderTimeInForce, expiresAt: any, type: Types.OrderType, reference?: string | null, postOnly?: boolean | null, reduceOnly?: boolean | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null};
export type StopOrderFieldsFragment = { __typename?: 'StopOrder', id: string, ocoLinkId?: string | null, expiresAt?: any | null, expiryStrategy?: Types.StopOrderExpiryStrategy | null, triggerDirection: Types.StopOrderTriggerDirection, status: Types.StopOrderStatus, createdAt: any, updatedAt?: any | null, partyId: string, marketId: string, trigger?: { __typename?: 'StopOrderPrice', price: string } | { __typename?: 'StopOrderTrailingPercentOffset', trailingPercentOffset: string } | null, submission: { __typename?: 'OrderSubmission', marketId: string, price: string, size: string, side: Types.Side, timeInForce: Types.OrderTimeInForce, expiresAt: any, type: Types.OrderType, reference?: string | null, postOnly?: boolean | null, reduceOnly?: boolean | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null } };
@@ -43,13 +43,6 @@ export type StopOrdersQueryVariables = Types.Exact<{
export type StopOrdersQuery = { __typename?: 'Query', stopOrders?: { __typename?: 'StopOrderConnection', edges?: Array<{ __typename?: 'StopOrderEdge', node?: { __typename?: 'StopOrder', id: string, ocoLinkId?: string | null, expiresAt?: any | null, expiryStrategy?: Types.StopOrderExpiryStrategy | null, triggerDirection: Types.StopOrderTriggerDirection, status: Types.StopOrderStatus, createdAt: any, updatedAt?: any | null, partyId: string, marketId: string, trigger?: { __typename?: 'StopOrderPrice', price: string } | { __typename?: 'StopOrderTrailingPercentOffset', trailingPercentOffset: string } | null, submission: { __typename?: 'OrderSubmission', marketId: string, price: string, size: string, side: Types.Side, timeInForce: Types.OrderTimeInForce, expiresAt: any, type: Types.OrderType, reference?: string | null, postOnly?: boolean | null, reduceOnly?: boolean | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null } } | null }> | null } | null };
export type StopOrderByIdQueryVariables = Types.Exact<{
stopOrderId: Types.Scalars['ID'];
}>;
export type StopOrderByIdQuery = { __typename?: 'Query', stopOrder?: { __typename?: 'StopOrder', id: string, ocoLinkId?: string | null, expiresAt?: any | null, expiryStrategy?: Types.StopOrderExpiryStrategy | null, triggerDirection: Types.StopOrderTriggerDirection, status: Types.StopOrderStatus, createdAt: any, updatedAt?: any | null, partyId: string, marketId: string, trigger?: { __typename?: 'StopOrderPrice', price: string } | { __typename?: 'StopOrderTrailingPercentOffset', trailingPercentOffset: string } | null, submission: { __typename?: 'OrderSubmission', marketId: string, price: string, size: string, side: Types.Side, timeInForce: Types.OrderTimeInForce, expiresAt: any, type: Types.OrderType, reference?: string | null, postOnly?: boolean | null, reduceOnly?: boolean | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null } } | null };
export const OrderFieldsFragmentDoc = gql`
fragment OrderFields on Order {
id
@@ -316,39 +309,4 @@ export function useStopOrdersLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions
}
export type StopOrdersQueryHookResult = ReturnType<typeof useStopOrdersQuery>;
export type StopOrdersLazyQueryHookResult = ReturnType<typeof useStopOrdersLazyQuery>;
export type StopOrdersQueryResult = Apollo.QueryResult<StopOrdersQuery, StopOrdersQueryVariables>;
export const StopOrderByIdDocument = gql`
query StopOrderById($stopOrderId: ID!) {
stopOrder(id: $stopOrderId) {
...StopOrderFields
}
}
${StopOrderFieldsFragmentDoc}`;
/**
* __useStopOrderByIdQuery__
*
* To run a query within a React component, call `useStopOrderByIdQuery` and pass it any options that fit your needs.
* When your component renders, `useStopOrderByIdQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useStopOrderByIdQuery({
* variables: {
* stopOrderId: // value for 'stopOrderId'
* },
* });
*/
export function useStopOrderByIdQuery(baseOptions: Apollo.QueryHookOptions<StopOrderByIdQuery, StopOrderByIdQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<StopOrderByIdQuery, StopOrderByIdQueryVariables>(StopOrderByIdDocument, options);
}
export function useStopOrderByIdLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<StopOrderByIdQuery, StopOrderByIdQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<StopOrderByIdQuery, StopOrderByIdQueryVariables>(StopOrderByIdDocument, options);
}
export type StopOrderByIdQueryHookResult = ReturnType<typeof useStopOrderByIdQuery>;
export type StopOrderByIdLazyQueryHookResult = ReturnType<typeof useStopOrderByIdLazyQuery>;
export type StopOrderByIdQueryResult = Apollo.QueryResult<StopOrderByIdQuery, StopOrderByIdQueryVariables>;
export type StopOrdersQueryResult = Apollo.QueryResult<StopOrdersQuery, StopOrdersQueryVariables>;
@@ -114,11 +114,9 @@ describe('OrderListTable', () => {
it('should apply correct formatting applied for an iceberg order', async () => {
const icebergOrder = {
...limitOrder,
size: '100',
remaining: '50',
icebergOrder: {
__typename: 'IcebergOrder',
minimumVisibleSize: '1',
minimumVisibleSize: '100',
peakSize: '50',
reservedRemaining: '50',
} as OrderFieldsFragment['icebergOrder'],
@@ -129,8 +127,8 @@ describe('OrderListTable', () => {
const cells = screen.getAllByRole('gridcell');
const expectedValues: string[] = [
icebergOrder.market?.tradableInstrument.instrument.code || '',
'0.00',
'+1.00',
'0.05',
'0.10',
Schema.OrderTypeMapping[
icebergOrder.type || Schema.OrderType.TYPE_LIMIT
] + ' (Iceberg)',
@@ -86,13 +86,21 @@ export const OrderListTable = memo<
valueGetter: ({ data }: VegaValueGetterParams<Order>) => {
if (data?.icebergOrder) {
return data?.size && data.market
? BigInt(data.size) -
BigInt(data.remaining) -
BigInt(data.icebergOrder.reservedRemaining)
? toBigNum(
(
BigInt(data.size) -
BigInt(data.remaining) -
BigInt(data.icebergOrder.reservedRemaining)
).toString(),
data.market.positionDecimalPlaces ?? 0
).toNumber()
: undefined;
}
return data?.size && data.market
? BigInt(data.size) - BigInt(data.remaining)
? toBigNum(
(BigInt(data.size) - BigInt(data.remaining)).toString(),
data.market.positionDecimalPlaces ?? 0
).toNumber()
: undefined;
},
valueFormatter: ({
@@ -106,8 +114,8 @@ export const OrderListTable = memo<
return '-';
}
return addDecimalsFormatNumber(
value,
data.market.positionDecimalPlaces ?? 0
(BigInt(data.size) - BigInt(data.remaining)).toString(),
data.market.positionDecimalPlaces
);
},
minWidth: 50,
@@ -3,7 +3,6 @@ import {
getDateTimeFormat,
isNumeric,
toBigNum,
formatTrigger,
} from '@vegaprotocol/utils';
import { t } from '@vegaprotocol/i18n';
import * as Schema from '@vegaprotocol/types';
@@ -56,8 +55,29 @@ export const StopOrdersTable = memo<
sortable: false,
valueFormatter: ({
data,
}: VegaValueFormatterParams<StopOrder, 'trigger'>): string =>
data ? formatTrigger(data, data.market.decimalPlaces) : '',
value,
}: VegaValueFormatterParams<StopOrder, 'trigger'>): string => {
if (data && value?.__typename === 'StopOrderPrice') {
return `${t('Mark')} ${
data?.triggerDirection ===
Schema.StopOrderTriggerDirection.TRIGGER_DIRECTION_FALLS_BELOW
? '<'
: '>'
} ${addDecimalsFormatNumber(
value.price,
data.market.decimalPlaces
)}`;
}
if (data && value?.__typename === 'StopOrderTrailingPercentOffset') {
return `${t('Mark')} ${
data?.triggerDirection ===
Schema.StopOrderTriggerDirection.TRIGGER_DIRECTION_FALLS_BELOW
? '+'
: '-'
}${(Number(value.trailingPercentOffset) * 100).toFixed(1)}%`;
}
return '-';
},
minWidth: 100,
},
{
@@ -136,12 +136,15 @@ export const AnchorButton = forwardRef<HTMLAnchorElement, AnchorButtonProps>(
}
);
type ButtonLinkProps = Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'style'>;
type ButtonLinkProps = Omit<
ButtonHTMLAttributes<HTMLButtonElement>,
'className' | 'style'
>;
export const ButtonLink = forwardRef<HTMLButtonElement, ButtonLinkProps>(
({ type = 'button', className, ...props }, ref) => {
const style = classnames('inline underline', className);
return <button ref={ref} className={style} type={type} {...props} />;
({ type = 'button', ...props }, ref) => {
const className = classnames('inline underline');
return <button ref={ref} className={className} type={type} {...props} />;
}
);
-1
View File
@@ -3,4 +3,3 @@ export * from './number';
export * from './range';
export * from './size';
export * from './strings';
export * from './trigger';
-27
View File
@@ -1,27 +0,0 @@
import * as Schema from '@vegaprotocol/types';
import { t } from '@vegaprotocol/i18n';
import { addDecimalsFormatNumber } from './number';
export const formatTrigger = (
data: Pick<Schema.StopOrder, 'trigger' | 'triggerDirection'> | undefined,
marketDecimalPlaces: number,
defaultValue = '-'
) => {
if (data && data?.trigger?.__typename === 'StopOrderPrice') {
return `${t('Mark')} ${
data?.triggerDirection ===
Schema.StopOrderTriggerDirection.TRIGGER_DIRECTION_FALLS_BELOW
? '<'
: '>'
} ${addDecimalsFormatNumber(data.trigger.price, marketDecimalPlaces)}`;
}
if (data && data?.trigger?.__typename === 'StopOrderTrailingPercentOffset') {
return `${t('Mark')} ${
data?.triggerDirection ===
Schema.StopOrderTriggerDirection.TRIGGER_DIRECTION_FALLS_BELOW
? '+'
: '-'
}${(Number(data?.trigger.trailingPercentOffset) * 100).toFixed(1)}%`;
}
return defaultValue;
};
@@ -12,7 +12,6 @@ import {
getVegaTransactionContentIntent,
} from './use-vega-transaction-toasts';
import { Intent } from '@vegaprotocol/ui-toolkit';
import type { OrderByIdQuery, StopOrderByIdQuery } from '@vegaprotocol/orders';
jest.mock('@vegaprotocol/assets', () => {
const A1 = {
@@ -24,7 +23,7 @@ jest.mock('@vegaprotocol/assets', () => {
};
return {
...jest.requireActual('@vegaprotocol/assets'),
useAssetsMapProvider: jest.fn(() => ({ data: { [A1.id]: A1 } })),
useAssetsDataProvider: jest.fn(() => ({ data: [A1] })),
};
});
@@ -51,7 +50,7 @@ jest.mock('@vegaprotocol/markets', () => {
};
return {
...jest.requireActual('@vegaprotocol/markets'),
useMarketsMapProvider: jest.fn(() => ({ data: { [M1.id]: M1 } })),
useMarketList: jest.fn(() => ({ data: [M1] })),
};
});
@@ -60,64 +59,20 @@ jest.mock('@vegaprotocol/orders', () => {
...jest.requireActual('@vegaprotocol/orders'),
useOrderByIdQuery: jest.fn(({ variables: { orderId } }) => {
if (orderId === '0') {
const data: OrderByIdQuery = {
orderByID: {
id: '0',
side: 'SIDE_BUY',
size: '10',
remaining: '10',
timeInForce: 'TIME_IN_FORCE_FOK',
type: 'TYPE_MARKET',
price: '1234',
createdAt: new Date(),
status: 'STATUS_ACTIVE',
market: { id: 'market-1' },
},
} as OrderByIdQuery;
return {
data,
};
} else {
return { data: undefined };
}
}),
useStopOrderByIdQuery: jest.fn(({ variables: { stopOrderId } }) => {
if (stopOrderId === '0') {
const data: StopOrderByIdQuery = {
stopOrder: {
id: '0',
ocoLinkId: null,
expiresAt: null,
expiryStrategy: null,
triggerDirection: 'TRIGGER_DIRECTION_RISES_ABOVE',
status: 'STATUS_CANCELLED',
createdAt: '2023-08-03T07:12:36.325927Z',
updatedAt: null,
partyId: 'party-id',
marketId: 'market-1',
trigger: {
price: '1234',
__typename: 'StopOrderPrice',
},
submission: {
marketId: 'market-1',
price: '1234',
data: {
orderByID: {
id: '0',
side: 'SIDE_BUY',
size: '10',
side: 'SIDE_SELL',
timeInForce: 'TIME_IN_FORCE_FOK',
expiresAt: null,
type: 'TYPE_MARKET',
reference: '',
peggedOrder: null,
postOnly: false,
reduceOnly: true,
__typename: 'OrderSubmission',
price: '1234',
createdAt: new Date(),
status: 'STATUS_ACTIVE',
market: { id: 'market-1' },
},
__typename: 'StopOrder',
},
} as StopOrderByIdQuery;
return {
data,
};
} else {
return { data: undefined };
@@ -188,31 +143,6 @@ const submitOrder: VegaStoredTxState = {
},
};
const submitStopOrder: VegaStoredTxState = {
id: 0,
createdAt: new Date(),
updatedAt: new Date(),
body: {
stopOrdersSubmission: {
risesAbove: {
price: '1234',
orderSubmission: {
marketId: 'market-1',
side: Side.SIDE_BUY,
size: '10',
timeInForce: OrderTimeInForce.TIME_IN_FORCE_FOK,
type: OrderType.TYPE_MARKET,
},
},
},
},
status: VegaTxStatus.Default,
error: null,
txHash: null,
signature: null,
dialogOpen: false,
};
const editOrder: VegaStoredTxState = {
id: 0,
createdAt: new Date(),
@@ -278,23 +208,6 @@ const cancelAll: VegaStoredTxState = {
dialogOpen: false,
};
const cancelStopOrder: VegaStoredTxState = {
id: 0,
createdAt: new Date(),
updatedAt: new Date(),
body: {
stopOrdersCancellation: {
marketId: 'market-1',
stopOrderId: '0',
},
},
status: VegaTxStatus.Default,
error: null,
txHash: null,
signature: null,
dialogOpen: false,
};
const closePosition: VegaStoredTxState = {
id: 0,
createdAt: new Date(),
@@ -356,20 +269,12 @@ describe('VegaTransactionDetails', () => {
it.each([
{ tx: withdraw, details: 'Withdraw 12.34 $A' },
{ tx: submitOrder, details: 'Submit order - activeM1+0.10 @ 12.34 $A' },
{
tx: submitStopOrder,
details: 'Submit stop orderM1+0.10 @ ~ $AMark > 12.34',
},
{
tx: editOrder,
details: 'Edit order - activeM1+0.10 @ 12.34 $A+0.11 @ 10.00 $A',
},
{ tx: cancelOrder, details: 'Cancel orderM1+0.10 @ 12.34 $A' },
{ tx: cancelAll, details: 'Cancel all orders' },
{
tx: cancelStopOrder,
details: 'Cancel stop orderM1-0.10 @ 12.34 $AMark > 12.34',
},
{ tx: closePosition, details: 'Close position for M1' },
{ tx: batch, details: 'Batch market instruction' },
])('display details for transaction', ({ tx, details }) => {
@@ -386,18 +291,12 @@ describe('getVegaTransactionContentIntent', () => {
expect(getVegaTransactionContentIntent(submitOrder).intent).toBe(
Intent.Success
);
expect(getVegaTransactionContentIntent(submitStopOrder).intent).toBe(
Intent.Primary
);
expect(getVegaTransactionContentIntent(editOrder).intent).toBe(
Intent.Primary
);
expect(getVegaTransactionContentIntent(cancelOrder).intent).toBe(
Intent.Primary
);
expect(getVegaTransactionContentIntent(cancelStopOrder).intent).toBe(
Intent.Primary
);
expect(getVegaTransactionContentIntent(cancelAll).intent).toBe(
Intent.Primary
);
+39 -153
View File
@@ -5,10 +5,10 @@ import type {
BatchMarketInstructionSubmissionBody,
OrderAmendment,
OrderTxUpdateFieldsFragment,
OrderCancellationBody,
OrderSubmission,
VegaStoredTxState,
WithdrawalBusEventFieldsFragment,
StopOrdersSubmission,
} from '@vegaprotocol/wallet';
import {
isTransferTransaction,
@@ -36,10 +36,9 @@ import {
formatNumber,
toBigNum,
truncateByChars,
formatTrigger,
} from '@vegaprotocol/utils';
import { t } from '@vegaprotocol/i18n';
import { useAssetsMapProvider } from '@vegaprotocol/assets';
import { useAssetsDataProvider } from '@vegaprotocol/assets';
import { useEthWithdrawApprovalsStore } from './use-ethereum-withdraw-approvals-store';
import { DApp, EXPLORER_TX, useLinks } from '@vegaprotocol/environment';
import {
@@ -47,9 +46,8 @@ import {
getOrderToastTitle,
getRejectionReason,
useOrderByIdQuery,
useStopOrderByIdQuery,
} from '@vegaprotocol/orders';
import { useMarketsMapProvider } from '@vegaprotocol/markets';
import { useMarketList } from '@vegaprotocol/markets';
import type { Side } from '@vegaprotocol/types';
import { OrderStatusMapping } from '@vegaprotocol/types';
import { Size } from '@vegaprotocol/datagrid';
@@ -138,8 +136,8 @@ const SubmitOrderDetails = ({
data: OrderSubmission;
order?: OrderTxUpdateFieldsFragment;
}) => {
const { data: markets } = useMarketsMapProvider();
const market = markets?.[order?.marketId || ''];
const { data: markets } = useMarketList();
const market = markets?.find((m) => m.id === order?.marketId);
if (!market) return null;
const price = order ? order.price : data.price;
@@ -174,58 +172,6 @@ const SubmitOrderDetails = ({
);
};
const SubmitStopOrderDetails = ({ data }: { data: StopOrdersSubmission }) => {
const { data: markets } = useMarketsMapProvider();
const stopOrderSetup = data.risesAbove || data.fallsBelow;
if (!stopOrderSetup) return null;
const market = markets?.[stopOrderSetup?.orderSubmission.marketId];
if (!market || !stopOrderSetup) return null;
const { price, size, side } = stopOrderSetup.orderSubmission;
let trigger: Schema.StopOrderTrigger | null = null;
if (stopOrderSetup.price) {
trigger = { price: stopOrderSetup.price, __typename: 'StopOrderPrice' };
} else if (stopOrderSetup.trailingPercentOffset) {
trigger = {
trailingPercentOffset: stopOrderSetup.trailingPercentOffset,
__typename: 'StopOrderTrailingPercentOffset',
};
}
const triggerDirection = data.risesAbove
? Schema.StopOrderTriggerDirection.TRIGGER_DIRECTION_RISES_ABOVE
: Schema.StopOrderTriggerDirection.TRIGGER_DIRECTION_FALLS_BELOW;
return (
<Panel>
<h4>{t('Submit stop order')}</h4>
<p>{market?.tradableInstrument.instrument.code}</p>
<p>
<SizeAtPrice
meta={{
positionDecimalPlaces: market.positionDecimalPlaces,
decimalPlaces: market.decimalPlaces,
asset:
market.tradableInstrument.instrument.product.settlementAsset
.symbol,
}}
side={side}
size={size}
price={price}
/>
<br />
{trigger &&
formatTrigger(
{
triggerDirection,
trigger,
},
market.decimalPlaces,
''
)}
</p>
</Panel>
);
};
const EditOrderDetails = ({
data,
order,
@@ -237,12 +183,13 @@ const EditOrderDetails = ({
variables: { orderId: data.orderId },
fetchPolicy: 'no-cache',
});
const { data: markets } = useMarketsMapProvider();
const { data: markets } = useMarketList();
const originalOrder = order || orderById?.orderByID;
const marketId = order?.marketId || orderById?.orderByID.market.id;
const market = markets?.[marketId || ''];
if (!originalOrder || !market) return null;
if (!originalOrder) return null;
const market = markets?.find((m) => m.id === marketId);
if (!market) return null;
const original = (
<SizeAtPrice
@@ -298,11 +245,11 @@ const CancelOrderDetails = ({
const { data: orderById } = useOrderByIdQuery({
variables: { orderId },
});
const { data: markets } = useMarketsMapProvider();
const { data: markets } = useMarketList();
const originalOrder = orderById?.orderByID;
if (!originalOrder) return null;
const market = markets?.[originalOrder.market.id];
const market = markets?.find((m) => m.id === originalOrder.market.id);
if (!market) return null;
const original = (
@@ -335,52 +282,15 @@ const CancelOrderDetails = ({
);
};
const CancelStopOrderDetails = ({ stopOrderId }: { stopOrderId: string }) => {
const { data: orderById } = useStopOrderByIdQuery({
variables: { stopOrderId },
});
const { data: markets } = useMarketsMapProvider();
const originalOrder = orderById?.stopOrder;
if (!originalOrder) return null;
const market = markets?.[originalOrder.marketId];
if (!market) return null;
const original = (
<>
<SizeAtPrice
side={originalOrder.submission.side}
size={originalOrder.submission.size}
price={originalOrder.submission.price}
meta={{
positionDecimalPlaces: market.positionDecimalPlaces,
decimalPlaces: market.decimalPlaces,
asset:
market.tradableInstrument.instrument.product.settlementAsset.symbol,
}}
/>
<br />
{formatTrigger(originalOrder, market.decimalPlaces, '')}
</>
);
return (
<Panel title={stopOrderId}>
<h4>{t('Cancel stop order')}</h4>
<p>{market?.tradableInstrument.instrument.code}</p>
<p>
<s>{original}</s>
</p>
</Panel>
);
};
export const VegaTransactionDetails = ({ tx }: { tx: VegaStoredTxState }) => {
const { data: assets } = useAssetsMapProvider();
const { data: markets } = useMarketsMapProvider();
const { data: assets } = useAssetsDataProvider();
const { data: markets } = useMarketList();
if (isWithdrawTransaction(tx.body)) {
const transactionDetails = tx.body;
const asset = assets?.[transactionDetails.withdrawSubmission.asset];
const asset = assets?.find(
(a) => a.id === transactionDetails.withdrawSubmission.asset
);
if (asset) {
const num = formatNumber(
toBigNum(transactionDetails.withdrawSubmission.amount, asset.decimals),
@@ -402,11 +312,15 @@ export const VegaTransactionDetails = ({ tx }: { tx: VegaStoredTxState }) => {
);
}
if (isStopOrdersSubmissionTransaction(tx.body)) {
return <SubmitStopOrderDetails data={tx.body.stopOrdersSubmission} />;
}
if (isOrderCancellationTransaction(tx.body)) {
// CANCEL ALL (from Portfolio)
if (
tx.body.orderCancellation.marketId === undefined &&
tx.body.orderCancellation.orderId === undefined
) {
return <Panel>{t('Cancel all orders')}</Panel>;
}
// CANCEL
if (
tx.body.orderCancellation.orderId &&
@@ -422,50 +336,22 @@ export const VegaTransactionDetails = ({ tx }: { tx: VegaStoredTxState }) => {
// CANCEL ALL (from Trading)
if (tx.body.orderCancellation.marketId) {
const marketName =
markets?.[tx.body.orderCancellation.marketId]?.tradableInstrument
.instrument.code;
if (marketName) {
return (
<Panel>
{t('Cancel all orders for')} <strong>{marketName}</strong>
</Panel>
);
}
}
// CANCEL ALL (from Portfolio)
return <Panel>{t('Cancel all orders')}</Panel>;
}
if (isStopOrdersCancellationTransaction(tx.body)) {
// CANCEL
if (
tx.body.stopOrdersCancellation.stopOrderId &&
tx.body.stopOrdersCancellation.marketId
) {
const marketName = markets?.find(
(m) =>
m.id === (tx.body as OrderCancellationBody).orderCancellation.marketId
)?.tradableInstrument.instrument.code;
return (
<CancelStopOrderDetails
stopOrderId={String(tx.body.stopOrdersCancellation.stopOrderId)}
/>
<Panel>
{marketName ? (
<>
{t('Cancel all orders for')} <strong>{marketName}</strong>
</>
) : (
t('Cancel all orders')
)}
</Panel>
);
}
// CANCEL ALL for market
if (tx.body.stopOrdersCancellation.marketId) {
const marketName =
markets?.[tx.body.stopOrdersCancellation.marketId]?.tradableInstrument
.instrument.code;
if (marketName) {
return (
<Panel>
{t('Cancel all stop orders for')} <strong>{marketName}</strong>
</Panel>
);
}
}
// CANCEL ALL
return <Panel>{t('Cancel all stop orders')}</Panel>;
}
if (isOrderAmendmentTransaction(tx.body)) {
@@ -482,7 +368,7 @@ export const VegaTransactionDetails = ({ tx }: { tx: VegaStoredTxState }) => {
const marketId = first(
transaction.batchMarketInstructions.cancellations
)?.marketId;
const market = markets?.[marketId || ''];
const market = marketId && markets?.find((m) => m.id === marketId);
if (market) {
return (
<Panel>
@@ -499,7 +385,7 @@ export const VegaTransactionDetails = ({ tx }: { tx: VegaStoredTxState }) => {
if (isTransferTransaction(tx.body)) {
const { amount, to, asset } = tx.body.transfer;
const transferAsset = assets?.[asset];
const transferAsset = assets?.find((a) => a.id === asset);
// only render if we have an asset to avoid unformatted amounts showing
if (transferAsset) {
const value = addDecimalsFormatNumber(amount, transferAsset.decimals);
-9
View File
@@ -117,15 +117,6 @@ When I look into market info I **Must** see following governance information:
- Proposal: (<a name="6002-MDET-301" href="#6002-MDET-301">6002-MDET-301</a>)
- link to governance proposal
- link to propose a change to market
- Succession line: (<a name="6002-MDET-302" href="#6002-MDET-302">6002-MDET-302</a>):
a list consisting of an origin market and all of its successors one-by-one.
The list **Should** contain:
- Market Code which links to the corresponding governance proposal
- Market Name
- Market ID
When I look at the succession line list I **Should** easily distinguish which market is the currently viewed market so I can see the ancestor-descendant relations between the current and other markets on the list.
## Market successor