chore(2415): get rid of polling queries on deal ticket (#2427)

* chore: get rid of polling queries on dael ticket

* chore: get rid of polling queries on dael ticket - fix tests

* chore: get rid of polling queries on deal ticket - fix linter

* chore: get rid of polling queries on deal ticket - fix linter

* chore: get rid of polling queries on deal ticket - adjust int test

* chore: get rid of polling queries on deal ticket - adjust int test in console-lite

* chore: get rid of polling queries on deal ticket - adjust unit some test

* chore: get rid of polling queries on deal ticket - adjust unit some test

* chore: get rid of polling queries on deal ticket - clean up some redundant types

* chore: get rid of polling queries on deal ticket - clean up some redundant files
This commit is contained in:
macqbat 2022-12-20 10:01:10 +01:00 committed by GitHub
parent 07b766e4d2
commit b9ff2388db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
48 changed files with 514 additions and 1382 deletions

View File

@ -7,11 +7,7 @@ import {
generateSimpleMarkets,
} from '../support/mocks/generate-markets';
import { generateMarketTags } from '../support/mocks/generate-market-tags';
import { generateMarketPositions } from '../support/mocks/generate-market-positions';
import { generateEstimateOrder } from '../support/mocks/generate-estimate-order';
import { generatePartyBalance } from '../support/mocks/generate-party-balance';
import { generatePartyMarketData } from '../support/mocks/generate-party-market-data';
import { generateMarketMarkPrice } from '../support/mocks/generate-market-mark-price';
import { generateMarketNames } from '../support/mocks/generate-market-names';
import { generateMarketDepth } from '../support/mocks/generate-market-depth';
import type { Market, MarketsQuery } from '@vegaprotocol/market-list';
@ -30,11 +26,7 @@ describe('market selector', { tags: '@smoke' }, () => {
aliasQuery(req, 'MarketData', generateMarketData());
aliasQuery(req, 'Market', generateMarket());
aliasQuery(req, 'MarketTags', generateMarketTags());
aliasQuery(req, 'MarketPositions', generateMarketPositions());
aliasQuery(req, 'EstimateOrder', generateEstimateOrder());
aliasQuery(req, 'PartyBalance', generatePartyBalance());
aliasQuery(req, 'PartyMarketData', generatePartyMarketData());
aliasQuery(req, 'MarketMarkPrice', generateMarketMarkPrice());
aliasQuery(req, 'MarketNames', generateMarketNames());
aliasQuery(req, 'MarketDepth', generateMarketDepth());
});

View File

@ -7,15 +7,14 @@ import {
generateMarketData,
} from '../support/mocks/generate-markets';
import { generateMarketTags } from '../support/mocks/generate-market-tags';
import { generateMarketPositions } from '../support/mocks/generate-market-positions';
import { generateEstimateOrder } from '../support/mocks/generate-estimate-order';
import { generatePartyBalance } from '../support/mocks/generate-party-balance';
import { generatePartyMarketData } from '../support/mocks/generate-party-market-data';
import { generateMarketMarkPrice } from '../support/mocks/generate-market-mark-price';
import { generateMarketDepth } from '../support/mocks/generate-market-depth';
import type { MarketsQuery, Market } from '@vegaprotocol/market-list';
import { generateChainId } from '../support/mocks/generate-chain-id';
import { generateStatistics } from '../support/mocks/generate-statistics';
import { generateAccounts } from '../support/mocks/generate-accounts';
import { generateAssets } from '../support/mocks/generate-assets';
import { generatePositions } from '../support/mocks/generate-positions';
describe('Market trade', { tags: '@smoke' }, () => {
let markets: Market[];
@ -28,14 +27,13 @@ describe('Market trade', { tags: '@smoke' }, () => {
aliasQuery(req, 'MarketsData', generateMarketsData());
aliasQuery(req, 'SimpleMarkets', generateSimpleMarkets());
aliasQuery(req, 'MarketTags', generateMarketTags());
aliasQuery(req, 'MarketPositions', generateMarketPositions());
aliasQuery(req, 'EstimateOrder', generateEstimateOrder());
aliasQuery(req, 'PartyBalance', generatePartyBalance());
aliasQuery(req, 'PartyMarketData', generatePartyMarketData());
aliasQuery(req, 'MarketMarkPrice', generateMarketMarkPrice());
aliasQuery(req, 'Accounts', generateAccounts());
aliasQuery(req, 'Assets', generateAssets());
aliasQuery(req, 'MarketDepth', generateMarketDepth());
aliasQuery(req, 'Market', generateMarket());
aliasQuery(req, 'MarketData', generateMarketData());
aliasQuery(req, 'Positions', generatePositions());
});
cy.visit('/markets');
cy.wait('@Markets').then((response) => {
@ -112,6 +110,24 @@ describe('Market trade', { tags: '@smoke' }, () => {
it('size slider should work well', () => {
if (markets?.length) {
const marketId = markets[1].id;
cy.mockGQL((req) => {
aliasQuery(
req,
'Market',
generateMarket({
market: {
id: marketId,
tradableInstrument: {
instrument: {
product: { settlementAsset: { id: 'asset-id-2' } },
},
},
},
})
);
});
cy.visit(`/trading/${marketId}`);
cy.visit(`/trading/${markets[1].id}`);
cy.connectVegaWallet();
cy.get('#step-1-control [aria-label^="Selected value"]').click();
@ -134,7 +150,24 @@ describe('Market trade', { tags: '@smoke' }, () => {
it('percentage selection should work well', () => {
if (markets?.length) {
cy.visit(`/trading/${markets[1].id}`);
const marketId = markets[1].id;
cy.mockGQL((req) => {
aliasQuery(
req,
'Market',
generateMarket({
market: {
id: marketId,
tradableInstrument: {
instrument: {
product: { settlementAsset: { id: 'asset-id-2' } },
},
},
},
})
);
});
cy.visit(`/trading/${marketId}`);
cy.connectVegaWallet();
cy.get('#step-1-control [aria-label^="Selected value"]').click();
cy.get('button[aria-label="Open short position"]').click();
@ -145,7 +178,7 @@ describe('Market trade', { tags: '@smoke' }, () => {
.find('button')
.should('have.text', '1');
cy.getByTestId('max-label').should('have.text', '21');
cy.getByTestId('max-label').should('have.text', '11');
cy.getByTestId('percentage-selector')
.find('button')
@ -155,7 +188,7 @@ describe('Market trade', { tags: '@smoke' }, () => {
.find('dd')
.eq(0)
.find('button')
.should('have.text', '21');
.should('have.text', '11');
}
});
@ -189,7 +222,24 @@ describe('Market trade', { tags: '@smoke' }, () => {
it('slippage value should be displayed', () => {
if (markets?.length) {
cy.visit(`/trading/${markets[1].id}`);
const marketId = markets[1].id;
cy.mockGQL((req) => {
aliasQuery(
req,
'Market',
generateMarket({
market: {
id: marketId,
tradableInstrument: {
instrument: {
product: { settlementAsset: { id: 'asset-id-2' } },
},
},
},
})
);
});
cy.visit(`/trading/${marketId}`);
cy.connectVegaWallet();
cy.get('#step-1-control [aria-label^="Selected value"]').click();
cy.get('button[aria-label="Open short position"]').click();
@ -205,7 +255,24 @@ describe('Market trade', { tags: '@smoke' }, () => {
it('allow slippage value to be adjusted', () => {
if (markets?.length) {
cy.visit(`/trading/${markets[1].id}`);
const marketId = markets[1].id;
cy.mockGQL((req) => {
aliasQuery(
req,
'Market',
generateMarket({
market: {
id: marketId,
tradableInstrument: {
instrument: {
product: { settlementAsset: { id: 'asset-id-2' } },
},
},
},
})
);
});
cy.visit(`/trading/${marketId}`);
cy.connectVegaWallet();
cy.get('#step-1-control [aria-label^="Selected value"]').click();
cy.get('button[aria-label="Open short position"]').click();

View File

@ -108,7 +108,7 @@ describe('Portfolio page tabs', { tags: '@smoke' }, () => {
});
it('data should be properly rendered', () => {
cy.get('.ag-center-cols-container .ag-row').should('have.length', 2);
cy.get('.ag-center-cols-container .ag-row').should('have.length', 1);
});
});

View File

@ -74,6 +74,21 @@ export const generateAccounts = (
},
},
},
{
__typename: 'AccountEdge',
node: {
type: Types.AccountType.ACCOUNT_TYPE_MARGIN,
asset: {
__typename: 'Asset',
id: 'asset-id-2',
},
balance: '265329',
market: {
id: '57fbaa322e97cfc8bb5f1de048c37e033c41b1ac1906d3aed9960912a067ef5a',
__typename: 'Market',
},
},
},
{
__typename: 'AccountEdge',
node: {

View File

@ -110,91 +110,91 @@ export const generateMarketDepth = (
],
buy: [
{
price: '9893005',
price: '9891005',
volume: '4',
numberOfOrders: '3',
__typename: 'PriceLevel',
},
{
price: '9893003',
price: '9890003',
volume: '2',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9893001',
price: '9889001',
volume: '1',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9892006',
price: '9888006',
volume: '3',
numberOfOrders: '2',
__typename: 'PriceLevel',
},
{
price: '9891006',
price: '9887006',
volume: '2',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9891001',
price: '9886001',
volume: '1',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9890101',
price: '9885101',
volume: '2',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9890091',
price: '9884091',
volume: '5',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9890081',
price: '9883081',
volume: '4',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9890050',
price: '9882050',
volume: '2',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9890040',
price: '9881040',
volume: '6',
numberOfOrders: '3',
__typename: 'PriceLevel',
},
{
price: '9890030',
price: '9880030',
volume: '6',
numberOfOrders: '2',
__typename: 'PriceLevel',
},
{
price: '9890021',
price: '9879021',
volume: '3',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9890011',
price: '9878011',
volume: '1',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9890001',
price: '9877001',
volume: '11',
numberOfOrders: '1',
__typename: 'PriceLevel',

View File

@ -1,9 +0,0 @@
export const generateMarketMarkPrice = () => {
return {
market: {
decimalPlaces: 5,
data: { markPrice: '692748', __typename: 'MarketData' },
__typename: 'Market',
},
};
};

View File

@ -1,72 +0,0 @@
import type { MarketPositionsQuery } from '@vegaprotocol/deal-ticket';
import * as Schema from '@vegaprotocol/types';
export const generateMarketPositions = (): MarketPositionsQuery => {
return {
party: {
id: '2e1ef32e5804e14232406aebaad719087d326afa5c648b7824d0823d8a46c8d1',
accountsConnection: {
__typename: 'AccountsConnection',
edges: [
{
__typename: 'AccountEdge',
node: {
__typename: 'AccountBalance',
type: Schema.AccountType.ACCOUNT_TYPE_GENERAL,
asset: {
decimals: 5,
},
balance: '400000000000000000000',
market: {
id: '2751c508f9759761f912890f37fb3f97a00300bf7685c02a56a86e05facfe221',
__typename: 'Market',
},
},
},
{
__typename: 'AccountEdge',
node: {
type: Schema.AccountType.ACCOUNT_TYPE_MARGIN,
asset: {
decimals: 5,
},
balance: '265329',
market: {
id: 'ca7768f6de84bf86a21bbb6b0109d9659c81917b0e0339b2c262566c9b581a15',
__typename: 'Market',
},
},
},
],
},
positionsConnection: {
edges: [
{
node: {
openVolume: '3',
market: {
id: '2751c508f9759761f912890f37fb3f97a00300bf7685c02a56a86e05facfe221',
__typename: 'Market',
},
__typename: 'Position',
},
__typename: 'PositionEdge',
},
{
node: {
openVolume: '12',
market: {
id: 'ca7768f6de84bf86a21bbb6b0109d9659c81917b0e0339b2c262566c9b581a15',
__typename: 'Market',
},
__typename: 'Position',
},
__typename: 'PositionEdge',
},
],
__typename: 'PositionConnection',
},
__typename: 'Party',
},
};
};

View File

@ -1392,12 +1392,15 @@ export const generatePositionsMarkets = () => {
};
};
export const generateMarket = (): MarketQuery => {
return {
export const generateMarket = (
override?: PartialDeep<MarketQuery>
): MarketQuery => {
const defaultResult = {
market: {
...singleMarket,
},
};
return merge(defaultResult, override);
};
export const generateMarketData = (): MarketDataQuery => {

View File

@ -1,81 +0,0 @@
import merge from 'lodash/merge';
import type { PartyBalanceQuery } from '@vegaprotocol/deal-ticket';
import type { PartialDeep } from 'type-fest';
import * as Types from '@vegaprotocol/types';
export const generatePartyBalance = (
override?: PartialDeep<PartyBalanceQuery>
): PartyBalanceQuery => {
const defaultResult: PartyBalanceQuery = {
party: {
accountsConnection: {
__typename: 'AccountsConnection',
edges: [
{
__typename: 'AccountEdge',
node: {
balance: '88474051',
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
asset: {
id: 'dai-id',
symbol: 'tDAI',
name: 'tDAI TEST',
decimals: 5,
__typename: 'Asset',
},
__typename: 'AccountBalance',
},
},
{
__typename: 'AccountEdge',
node: {
balance: '100000000',
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
asset: {
id: '8b52d4a3a4b0ffe733cddbc2b67be273816cfeb6ca4c8b339bac03ffba08e4e4',
symbol: 'tEURO',
name: 'tEURO TEST',
decimals: 5,
__typename: 'Asset',
},
__typename: 'AccountBalance',
},
},
{
__typename: 'AccountEdge',
node: {
balance: '3412867',
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
asset: {
id: 'dai-id',
symbol: 'tDAI',
name: 'tDAI TEST',
decimals: 5,
__typename: 'Asset',
},
__typename: 'AccountBalance',
},
},
{
__typename: 'AccountEdge',
node: {
balance: '70007',
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
asset: {
id: 'dai-id',
symbol: 'tDAI',
name: 'tDAI TEST',
decimals: 5,
__typename: 'Asset',
},
__typename: 'AccountBalance',
},
},
],
},
__typename: 'Party',
},
};
return merge(defaultResult, override);
};

View File

@ -1,40 +0,0 @@
import type { PartyMarketDataQuery } from '@vegaprotocol/deal-ticket';
import * as Types from '@vegaprotocol/types';
export const generatePartyMarketData = (): PartyMarketDataQuery => {
return {
party: {
id: '2e1ef32e5804e14232406aebaad719087d326afa5c648b7824d0823d8a46c8d1',
accountsConnection: {
__typename: 'AccountsConnection',
edges: [
{
__typename: 'AccountEdge',
node: {
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
balance: '1200000',
asset: { id: 'fBTC', decimals: 5, __typename: 'Asset' },
market: null,
__typename: 'AccountBalance',
},
},
{
__typename: 'AccountEdge',
node: {
__typename: 'AccountBalance',
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
balance: '0.000000001',
asset: {
__typename: 'Asset',
id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
decimals: 0,
},
},
},
],
},
marginsConnection: { edges: null, __typename: 'MarginConnection' },
__typename: 'Party',
},
};
};

View File

@ -41,7 +41,7 @@ export const generatePositions = (
averageEntryPrice: '84400088',
updatedAt: '2022-07-28T14:53:54.725477Z',
market: {
id: '5a4b0b9e9c0629f0315ec56fcb7bd444b0c6e4da5ec7677719d502626658a376',
id: '57fbaa322e97cfc8bb5f1de048c37e033c41b1ac1906d3aed9960912a067ef5a',
__typename: 'Market',
},
__typename: 'Position',

View File

@ -1,18 +0,0 @@
query PartyBalanceQuery($partyId: ID!) {
party(id: $partyId) {
accountsConnection {
edges {
node {
type
balance
asset {
id
symbol
name
decimals
}
}
}
}
}
}

View File

@ -1,61 +0,0 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type PartyBalanceQueryQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
}>;
export type PartyBalanceQueryQuery = { __typename?: 'Query', party?: { __typename?: 'Party', accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number } } } | null> | null } | null } | null };
export const PartyBalanceQueryDocument = gql`
query PartyBalanceQuery($partyId: ID!) {
party(id: $partyId) {
accountsConnection {
edges {
node {
type
balance
asset {
id
symbol
name
decimals
}
}
}
}
}
}
`;
/**
* __usePartyBalanceQueryQuery__
*
* To run a query within a React component, call `usePartyBalanceQueryQuery` and pass it any options that fit your needs.
* When your component renders, `usePartyBalanceQueryQuery` 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 } = usePartyBalanceQueryQuery({
* variables: {
* partyId: // value for 'partyId'
* },
* });
*/
export function usePartyBalanceQueryQuery(baseOptions: Apollo.QueryHookOptions<PartyBalanceQueryQuery, PartyBalanceQueryQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<PartyBalanceQueryQuery, PartyBalanceQueryQueryVariables>(PartyBalanceQueryDocument, options);
}
export function usePartyBalanceQueryLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<PartyBalanceQueryQuery, PartyBalanceQueryQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<PartyBalanceQueryQuery, PartyBalanceQueryQueryVariables>(PartyBalanceQueryDocument, options);
}
export type PartyBalanceQueryQueryHookResult = ReturnType<typeof usePartyBalanceQueryQuery>;
export type PartyBalanceQueryLazyQueryHookResult = ReturnType<typeof usePartyBalanceQueryLazyQuery>;
export type PartyBalanceQueryQueryResult = Apollo.QueryResult<PartyBalanceQueryQuery, PartyBalanceQueryQueryVariables>;

View File

@ -1,9 +1,13 @@
import React from 'react';
import { render } from '@testing-library/react';
import type { AccountFragment } from '@vegaprotocol/deal-ticket';
import { DealTicketBalance } from './deal-ticket-balance';
import * as Schema from '@vegaprotocol/types';
import { MockedProvider } from '@apollo/client/testing';
import type { MarketDealTicketAsset } from '@vegaprotocol/market-list';
import { DealTicketBalance } from './deal-ticket-balance';
jest.mock('@vegaprotocol/wallet', () => ({
...jest.requireActual('@vegaprotocol/wallet'),
useVegaWallet: jest.fn().mockReturnValue('wallet-pub-key'),
}));
const tDAI: MarketDealTicketAsset = {
__typename: 'Asset',
@ -13,23 +17,20 @@ const tDAI: MarketDealTicketAsset = {
decimals: 2,
};
const accounts: AccountFragment[] = [
{
__typename: 'AccountBalance',
type: Schema.AccountType.ACCOUNT_TYPE_GENERAL,
balance: '1000000',
asset: tDAI,
},
];
let mockAccountBalance: {
accountBalance: string;
accountDecimals: number | null;
} = { accountBalance: '1000000', accountDecimals: 2 };
jest.mock('@vegaprotocol/accounts', () => ({
...jest.requireActual('@vegaprotocol/accounts'),
useAccountBalance: jest.fn(() => mockAccountBalance),
}));
describe('DealTicketBalance', function () {
it('should render the balance', () => {
const { getByText, getByRole } = render(
<DealTicketBalance
settlementAsset={tDAI}
accounts={accounts}
isWalletConnected
/>
<DealTicketBalance settlementAsset={tDAI} isWalletConnected />,
{ wrapper: MockedProvider }
);
expect(getByRole('complementary')).toHaveAccessibleName('tDAI Balance');
@ -39,11 +40,8 @@ describe('DealTicketBalance', function () {
it('should prompt to connect wallet', () => {
const { getByText } = render(
<DealTicketBalance
settlementAsset={tDAI}
accounts={accounts}
isWalletConnected={false}
/>
<DealTicketBalance settlementAsset={tDAI} isWalletConnected={false} />,
{ wrapper: MockedProvider }
);
expect(
@ -52,12 +50,10 @@ describe('DealTicketBalance', function () {
});
it('should display zero balance', () => {
mockAccountBalance = { accountBalance: '', accountDecimals: null };
const { getByText } = render(
<DealTicketBalance
settlementAsset={tDAI}
accounts={[]}
isWalletConnected={true}
/>
<DealTicketBalance settlementAsset={tDAI} isWalletConnected={true} />,
{ wrapper: MockedProvider }
);
expect(getByText('No tDAI left to trade')).toBeInTheDocument();

View File

@ -1,41 +1,38 @@
import classNames from 'classnames';
import { addDecimalsFormatNumber, t } from '@vegaprotocol/react-helpers';
import * as Schema from '@vegaprotocol/types';
import type { AccountFragment } from '@vegaprotocol/deal-ticket';
import {
addDecimalsFormatNumber,
t,
toBigNum,
} from '@vegaprotocol/react-helpers';
import type { MarketDealTicket } from '@vegaprotocol/market-list';
import { useSettlementAccount } from '@vegaprotocol/deal-ticket';
import { useAccountBalance } from '@vegaprotocol/accounts';
interface DealTicketBalanceProps {
settlementAsset: MarketDealTicket['tradableInstrument']['instrument']['product']['settlementAsset'];
accounts: AccountFragment[];
isWalletConnected: boolean;
className?: string;
}
export const DealTicketBalance = ({
settlementAsset,
accounts,
isWalletConnected,
className = '',
}: DealTicketBalanceProps) => {
const settlementAssetId = settlementAsset?.id;
const settlementAssetSymbol = settlementAsset?.symbol;
const settlementAccount = useSettlementAccount(
settlementAssetId,
accounts,
Schema.AccountType.ACCOUNT_TYPE_GENERAL
);
const { accountBalance, accountDecimals } =
useAccountBalance(settlementAssetId) || {};
const settlementBalance = toBigNum(accountBalance || 0, accountDecimals || 0);
const formattedNumber =
settlementAccount?.balance &&
settlementAccount.asset.decimals &&
addDecimalsFormatNumber(
settlementAccount.balance,
settlementAccount.asset.decimals
);
accountBalance &&
accountDecimals &&
addDecimalsFormatNumber(accountBalance, accountDecimals);
const balance = (
<p className="text-blue text-lg font-semibold">
{settlementAccount
{!settlementBalance.isZero()
? t(`${formattedNumber}`)
: `No ${settlementAssetSymbol} left to trade`}
</p>

View File

@ -1,14 +1,7 @@
import { useParams } from 'react-router-dom';
import {
DealTicketManager,
usePartyBalanceQuery,
} from '@vegaprotocol/deal-ticket';
import { DealTicketManager } from '@vegaprotocol/deal-ticket';
import { Loader, Splash } from '@vegaprotocol/ui-toolkit';
import {
t,
useDataProvider,
removePaginationWrapper,
} from '@vegaprotocol/react-helpers';
import { t, useDataProvider } from '@vegaprotocol/react-helpers';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { DealTicketSteps } from './deal-ticket-steps';
import { DealTicketBalance } from './deal-ticket-balance';
@ -29,11 +22,6 @@ export const DealTicketContainer = () => {
const { marketId } = useParams<{ marketId: string }>();
const { pubKey } = useVegaWallet();
const { data: partyData } = usePartyBalanceQuery({
variables: { partyId: pubKey || '' },
skip: !pubKey,
});
const variables = useMemo(
() => ({
marketId: marketId || '',
@ -49,10 +37,6 @@ export const DealTicketContainer = () => {
skip: !marketId,
});
const accounts = removePaginationWrapper(
partyData?.party?.accountsConnection?.edges
);
const loader = <Loader />;
if (marketId && data) {
const balance = (
@ -61,7 +45,6 @@ export const DealTicketContainer = () => {
settlementAsset={
data.tradableInstrument.instrument.product?.settlementAsset
}
accounts={accounts || []}
isWalletConnected={!!pubKey}
/>
);

View File

@ -6,7 +6,6 @@ import {
getDefaultOrder,
useOrderCloseOut,
useOrderMargin,
usePartyBalanceQuery,
useMaximumPositionSize,
useCalculateSlippage,
validateAmount,
@ -24,7 +23,6 @@ import {
addDecimalsFormatNumber,
addDecimal,
formatNumber,
removePaginationWrapper,
} from '@vegaprotocol/react-helpers';
import {
useOrderSubmit,
@ -77,17 +75,7 @@ export const DealTicketSteps = ({ market }: DealTicketMarketProps) => {
});
const { submit, transaction, finalizedOrder, Dialog } = useOrderSubmit();
const { data: partyBalance } = usePartyBalanceQuery({
variables: { partyId: pubKey || '' },
skip: !pubKey,
});
const accounts = removePaginationWrapper(
partyBalance?.party?.accountsConnection?.edges
);
const maxTrade = useMaximumPositionSize({
partyId: pubKey || '',
accounts: accounts,
marketId: market.id,
settlementAssetId:
market.tradableInstrument.instrument.product.settlementAsset.id,
@ -98,7 +86,6 @@ export const DealTicketSteps = ({ market }: DealTicketMarketProps) => {
const estCloseOut = useOrderCloseOut({
order,
market,
partyData: partyBalance,
});
const slippage = useCalculateSlippage({ marketId: market.id, order });
const [slippageValue, setSlippageValue] = useState(

View File

@ -697,7 +697,7 @@ describe('account validation', { tags: '@regression' }, () => {
);
cy.getByTestId('dealticket-warning-margin').should(
'contain.text',
'10,000.00 tBTC currently required, 1,000.00 tBTC available'
'9,999.99 tBTC currently required, 1,000.00 tBTC available'
);
cy.getByTestId('deal-ticket-deposit-dialog-button').click();
cy.getByTestId('dialog-content')

View File

@ -1,12 +1,6 @@
import type { PartialDeep } from 'type-fest';
import merge from 'lodash/merge';
import * as Types from '@vegaprotocol/types';
import type {
EstimateOrderQuery,
MarketMarkPriceQuery,
PartyBalanceQuery,
PartyMarketDataQuery,
} from '@vegaprotocol/deal-ticket';
import type { EstimateOrderQuery } from '@vegaprotocol/deal-ticket';
const estimateOrderMock: EstimateOrderQuery = {
estimateOrder: {
@ -27,87 +21,3 @@ export const generateEstimateOrder = (
) => {
return merge(estimateOrderMock, override);
};
const marketMarkPriceMock: MarketMarkPriceQuery = {
market: {
__typename: 'Market',
decimalPlaces: 5,
data: {
__typename: 'MarketData',
markPrice: '100',
market: { __typename: 'Market', id: 'market-0' },
},
},
};
export const generateMarkPrice = () => {
return marketMarkPriceMock;
};
const partyBalanceMock: PartyBalanceQuery = {
party: {
__typename: 'Party',
accountsConnection: {
__typename: 'AccountsConnection',
edges: [
{
__typename: 'AccountEdge',
node: {
__typename: 'AccountBalance',
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
balance: '100',
asset: {
__typename: 'Asset',
id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
symbol: 'tBTC',
name: 'BTC',
decimals: 5,
},
},
},
],
},
},
};
export const generatePartyBalance = () => {
return partyBalanceMock;
};
export const generatePartyMarketData = (): PartyMarketDataQuery => {
return {
party: {
id: Cypress.env('VEGA_PUBLIC_KEY'),
accountsConnection: {
__typename: 'AccountsConnection',
edges: [
{
__typename: 'AccountEdge',
node: {
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
balance: '1200000',
asset: { id: 'fBTC', decimals: 5, __typename: 'Asset' },
market: null,
__typename: 'AccountBalance',
},
},
{
__typename: 'AccountEdge',
node: {
__typename: 'AccountBalance',
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
balance: '100',
asset: {
__typename: 'Asset',
id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
decimals: 5,
},
},
},
],
},
marginsConnection: { edges: null, __typename: 'MarginConnection' },
__typename: 'Party',
},
};
};

View File

@ -18,12 +18,7 @@ import { generateOrders } from './mocks/generate-orders';
import { generateMargins, generatePositions } from './mocks/generate-positions';
import { generateTrades } from './mocks/generate-trades';
import { generateWithdrawals } from './mocks/generate-withdrawals';
import {
generateEstimateOrder,
generateMarkPrice,
generatePartyBalance,
generatePartyMarketData,
} from './mocks/generate-fees';
import { generateEstimateOrder } from './mocks/generate-fees';
import { generateMarketProposals } from './mocks/generate-proposals';
import { generateStatistics } from './mocks/generate-statistics';
import { generateChainId } from './mocks/generate-chain-id';
@ -94,10 +89,7 @@ const mockTradingPage = (
aliasQuery(req, 'Withdrawals', generateWithdrawals());
aliasQuery(req, 'NetworkParams', generateNetworkParameters());
aliasQuery(req, 'EstimateOrder', generateEstimateOrder());
aliasQuery(req, 'MarketMarkPrice', generateMarkPrice());
aliasQuery(req, 'PartyBalance', generatePartyBalance());
aliasQuery(req, 'MarketPositions', generatePositions());
aliasQuery(req, 'PartyMarketData', generatePartyMarketData());
aliasQuery(req, 'ProposalsList', generateMarketProposals());
aliasQuery(req, 'Deposits', generateDeposits());
};

View File

@ -0,0 +1,15 @@
import type { Account } from './accounts-data-provider';
import * as Schema from '@vegaprotocol/types';
interface Props {
accounts: Account[] | null;
marketId: string;
}
export const getMarketAccount = ({ accounts, marketId }: Props) =>
accounts?.find((account) => {
return (
account.market?.id === marketId &&
account.type === Schema.AccountType.ACCOUNT_TYPE_MARGIN
);
}) || null;

View File

@ -6,3 +6,4 @@ export * from './accounts-manager';
export * from './breakdown-table';
export * from './use-account-balance';
export * from './get-settlement-account';
export * from './use-market-account-balance';

View File

@ -0,0 +1,43 @@
import { useCallback, useMemo, useState } from 'react';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { useDataProvider } from '@vegaprotocol/react-helpers';
import { accountsDataProvider } from './accounts-data-provider';
import type { Account } from './accounts-data-provider';
import { getMarketAccount } from './get-market-account';
export const useMarketAccountBalance = (marketId: string) => {
const { pubKey } = useVegaWallet();
const [accountBalance, setAccountBalance] = useState<string>('');
const [accountDecimals, setAccountDecimals] = useState<number | null>(null);
const variables = useMemo(() => {
return { partyId: pubKey || '' };
}, [pubKey]);
const update = useCallback(
({ data }: { data: Account[] | null }) => {
const account = getMarketAccount({ accounts: data, marketId });
if (accountBalance !== account?.balance) {
setAccountBalance(account?.balance || '');
}
if (accountDecimals !== account?.asset.decimals) {
setAccountDecimals(account?.asset.decimals || null);
}
return true;
},
[accountBalance, accountDecimals, marketId]
);
useDataProvider({
dataProvider: accountsDataProvider,
variables,
skip: !pubKey || !marketId,
update,
});
return useMemo(
() => ({
accountBalance,
accountDecimals,
}),
[accountBalance, accountDecimals]
);
};

View File

@ -1,11 +0,0 @@
query MarketMarkPrice($marketId: ID!) {
market(id: $marketId) {
decimalPlaces
data {
markPrice
market {
id
}
}
}
}

View File

@ -1,29 +0,0 @@
query MarketPositions($partyId: ID!) {
party(id: $partyId) {
id
accountsConnection {
edges {
node {
type
balance
asset {
decimals
}
market {
id
}
}
}
}
positionsConnection {
edges {
node {
openVolume
market {
id
}
}
}
}
}
}

View File

@ -1,22 +0,0 @@
query PartyBalance($partyId: ID!) {
party(id: $partyId) {
accountsConnection {
edges {
node {
...Account
}
}
}
}
}
fragment Account on AccountBalance {
type
balance
asset {
id
symbol
name
decimals
}
}

View File

@ -1,32 +0,0 @@
query PartyMarketData($partyId: ID!) {
party(id: $partyId) {
id
accountsConnection {
edges {
node {
type
balance
asset {
id
decimals
}
market {
id
}
}
}
}
marginsConnection {
edges {
node {
market {
id
}
initialLevel
maintenanceLevel
searchLevel
}
}
}
}
}

View File

@ -1,54 +0,0 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type MarketMarkPriceQueryVariables = Types.Exact<{
marketId: Types.Scalars['ID'];
}>;
export type MarketMarkPriceQuery = { __typename?: 'Query', market?: { __typename?: 'Market', decimalPlaces: number, data?: { __typename?: 'MarketData', markPrice: string, market: { __typename?: 'Market', id: string } } | null } | null };
export const MarketMarkPriceDocument = gql`
query MarketMarkPrice($marketId: ID!) {
market(id: $marketId) {
decimalPlaces
data {
markPrice
market {
id
}
}
}
}
`;
/**
* __useMarketMarkPriceQuery__
*
* To run a query within a React component, call `useMarketMarkPriceQuery` and pass it any options that fit your needs.
* When your component renders, `useMarketMarkPriceQuery` 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 } = useMarketMarkPriceQuery({
* variables: {
* marketId: // value for 'marketId'
* },
* });
*/
export function useMarketMarkPriceQuery(baseOptions: Apollo.QueryHookOptions<MarketMarkPriceQuery, MarketMarkPriceQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<MarketMarkPriceQuery, MarketMarkPriceQueryVariables>(MarketMarkPriceDocument, options);
}
export function useMarketMarkPriceLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<MarketMarkPriceQuery, MarketMarkPriceQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<MarketMarkPriceQuery, MarketMarkPriceQueryVariables>(MarketMarkPriceDocument, options);
}
export type MarketMarkPriceQueryHookResult = ReturnType<typeof useMarketMarkPriceQuery>;
export type MarketMarkPriceLazyQueryHookResult = ReturnType<typeof useMarketMarkPriceLazyQuery>;
export type MarketMarkPriceQueryResult = Apollo.QueryResult<MarketMarkPriceQuery, MarketMarkPriceQueryVariables>;

View File

@ -1,72 +0,0 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type MarketPositionsQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
}>;
export type MarketPositionsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', decimals: number }, market?: { __typename?: 'Market', id: string } | null } } | null> | null } | null, positionsConnection?: { __typename?: 'PositionConnection', edges?: Array<{ __typename?: 'PositionEdge', node: { __typename?: 'Position', openVolume: string, market: { __typename?: 'Market', id: string } } }> | null } | null } | null };
export const MarketPositionsDocument = gql`
query MarketPositions($partyId: ID!) {
party(id: $partyId) {
id
accountsConnection {
edges {
node {
type
balance
asset {
decimals
}
market {
id
}
}
}
}
positionsConnection {
edges {
node {
openVolume
market {
id
}
}
}
}
}
}
`;
/**
* __useMarketPositionsQuery__
*
* To run a query within a React component, call `useMarketPositionsQuery` and pass it any options that fit your needs.
* When your component renders, `useMarketPositionsQuery` 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 } = useMarketPositionsQuery({
* variables: {
* partyId: // value for 'partyId'
* },
* });
*/
export function useMarketPositionsQuery(baseOptions: Apollo.QueryHookOptions<MarketPositionsQuery, MarketPositionsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<MarketPositionsQuery, MarketPositionsQueryVariables>(MarketPositionsDocument, options);
}
export function useMarketPositionsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<MarketPositionsQuery, MarketPositionsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<MarketPositionsQuery, MarketPositionsQueryVariables>(MarketPositionsDocument, options);
}
export type MarketPositionsQueryHookResult = ReturnType<typeof useMarketPositionsQuery>;
export type MarketPositionsLazyQueryHookResult = ReturnType<typeof useMarketPositionsLazyQuery>;
export type MarketPositionsQueryResult = Apollo.QueryResult<MarketPositionsQuery, MarketPositionsQueryVariables>;

View File

@ -1,67 +0,0 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type PartyBalanceQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
}>;
export type PartyBalanceQuery = { __typename?: 'Query', party?: { __typename?: 'Party', accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number } } } | null> | null } | null } | null };
export type AccountFragment = { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number } };
export const AccountFragmentDoc = gql`
fragment Account on AccountBalance {
type
balance
asset {
id
symbol
name
decimals
}
}
`;
export const PartyBalanceDocument = gql`
query PartyBalance($partyId: ID!) {
party(id: $partyId) {
accountsConnection {
edges {
node {
...Account
}
}
}
}
}
${AccountFragmentDoc}`;
/**
* __usePartyBalanceQuery__
*
* To run a query within a React component, call `usePartyBalanceQuery` and pass it any options that fit your needs.
* When your component renders, `usePartyBalanceQuery` 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 } = usePartyBalanceQuery({
* variables: {
* partyId: // value for 'partyId'
* },
* });
*/
export function usePartyBalanceQuery(baseOptions: Apollo.QueryHookOptions<PartyBalanceQuery, PartyBalanceQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<PartyBalanceQuery, PartyBalanceQueryVariables>(PartyBalanceDocument, options);
}
export function usePartyBalanceLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<PartyBalanceQuery, PartyBalanceQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<PartyBalanceQuery, PartyBalanceQueryVariables>(PartyBalanceDocument, options);
}
export type PartyBalanceQueryHookResult = ReturnType<typeof usePartyBalanceQuery>;
export type PartyBalanceLazyQueryHookResult = ReturnType<typeof usePartyBalanceLazyQuery>;
export type PartyBalanceQueryResult = Apollo.QueryResult<PartyBalanceQuery, PartyBalanceQueryVariables>;

View File

@ -1,75 +0,0 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type PartyMarketDataQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
}>;
export type PartyMarketDataQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', id: string, decimals: number }, market?: { __typename?: 'Market', id: string } | null } } | null> | null } | null, marginsConnection?: { __typename?: 'MarginConnection', edges?: Array<{ __typename?: 'MarginEdge', node: { __typename?: 'MarginLevels', initialLevel: string, maintenanceLevel: string, searchLevel: string, market: { __typename?: 'Market', id: string } } }> | null } | null } | null };
export const PartyMarketDataDocument = gql`
query PartyMarketData($partyId: ID!) {
party(id: $partyId) {
id
accountsConnection {
edges {
node {
type
balance
asset {
id
decimals
}
market {
id
}
}
}
}
marginsConnection {
edges {
node {
market {
id
}
initialLevel
maintenanceLevel
searchLevel
}
}
}
}
}
`;
/**
* __usePartyMarketDataQuery__
*
* To run a query within a React component, call `usePartyMarketDataQuery` and pass it any options that fit your needs.
* When your component renders, `usePartyMarketDataQuery` 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 } = usePartyMarketDataQuery({
* variables: {
* partyId: // value for 'partyId'
* },
* });
*/
export function usePartyMarketDataQuery(baseOptions: Apollo.QueryHookOptions<PartyMarketDataQuery, PartyMarketDataQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<PartyMarketDataQuery, PartyMarketDataQueryVariables>(PartyMarketDataDocument, options);
}
export function usePartyMarketDataLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<PartyMarketDataQuery, PartyMarketDataQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<PartyMarketDataQuery, PartyMarketDataQueryVariables>(PartyMarketDataDocument, options);
}
export type PartyMarketDataQueryHookResult = ReturnType<typeof usePartyMarketDataQuery>;
export type PartyMarketDataLazyQueryHookResult = ReturnType<typeof usePartyMarketDataLazyQuery>;
export type PartyMarketDataQueryResult = Apollo.QueryResult<PartyMarketDataQuery, PartyMarketDataQueryVariables>;

View File

@ -1,14 +1,8 @@
export * from './__generated__/EstimateOrder';
export * from './__generated__/MarketMarkPrice';
export * from './__generated__/MarketPositions';
export * from './__generated__/PartyBalance';
export * from './__generated__/PartyMarketData';
export * from './use-calculate-slippage';
export * from './use-fee-deal-ticket-details';
export * from './use-market-data-mark-price';
export * from './use-market-positions';
export * from './use-maximum-position-size';
export * from './use-order-closeout';
export * from './use-order-margin';
export * from './use-order-margin-validation';
export * from './use-settlement-account';

View File

@ -16,7 +16,6 @@ import {
EST_MARGIN_TOOLTIP_TEXT,
NOTIONAL_SIZE_TOOLTIP_TEXT,
} from '../constants';
import { usePartyBalanceQuery } from './__generated__/PartyBalance';
import { useCalculateSlippage } from './use-calculate-slippage';
import { useOrderCloseOut } from './use-order-closeout';
import { useOrderMargin } from './use-order-margin';
@ -49,22 +48,16 @@ export const useFeeDealTicketDetails = (
return null;
}, [derivedPrice, order.side, slippage]);
const estMargin: OrderMargin | null = useOrderMargin({
const estMargin = useOrderMargin({
order,
market,
partyId: pubKey || '',
derivedPrice,
});
const { data: partyBalance } = usePartyBalanceQuery({
variables: { partyId: pubKey || '' },
skip: !pubKey,
});
const estCloseOut = useOrderCloseOut({
order,
market,
partyData: partyBalance,
});
const notionalSize = useMemo(() => {
@ -87,7 +80,6 @@ export const useFeeDealTicketDetails = (
estCloseOut,
slippage,
slippageAdjustedPrice,
partyData: partyBalance,
};
}, [
market,
@ -97,7 +89,6 @@ export const useFeeDealTicketDetails = (
estCloseOut,
slippage,
slippageAdjustedPrice,
partyBalance,
]);
};

View File

@ -1,21 +0,0 @@
import { useMemo, useRef } from 'react';
import type { MarketMarkPriceQuery } from './__generated__/MarketMarkPrice';
import { useMarketMarkPriceQuery } from './__generated__/MarketMarkPrice';
export const useMarketDataMarkPrice = (marketId: string) => {
const memoRef = useRef<MarketMarkPriceQuery | null>(null);
const { data } = useMarketMarkPriceQuery({
pollInterval: 5000,
variables: { marketId },
skip: !marketId,
});
return useMemo(() => {
if (
data &&
data.market?.data?.markPrice !== memoRef.current?.market?.data?.markPrice
) {
memoRef.current = data;
}
return memoRef.current;
}, [data, memoRef]);
};

View File

@ -1,60 +1,23 @@
import { renderHook } from '@testing-library/react';
import { MockedProvider } from '@apollo/client/testing';
import { useMarketPositions } from './use-market-positions';
let mockNotEmptyData = {
party: {
accountsConnection: {
edges: [
{
node: {
balance: '50001000000',
asset: {
decimals: 5,
},
market: {
id: 'marketId',
},
},
},
{
node: {
balance: '700000000000000000000000000000',
asset: {
decimals: 5,
},
market: {
id: 'someOtherMarketId',
},
},
},
],
},
positionsConnection: {
edges: [
{
node: {
openVolume: '100002',
market: {
id: 'marketId',
},
},
},
{
node: {
openVolume: '3',
market: {
id: 'someOtherMarketId',
},
},
},
],
},
},
};
jest.mock('@vegaprotocol/wallet', () => ({
...jest.requireActual('@vegaprotocol/wallet'),
useVegaWallet: jest.fn().mockReturnValue('wallet-pub-key'),
}));
let mockMarketAccountBalance: {
accountBalance: string;
accountDecimals: number | null;
} = { accountBalance: '50001000000', accountDecimals: 5 };
jest.mock('@vegaprotocol/accounts', () => ({
...jest.requireActual('@vegaprotocol/accounts'),
useMarketAccountBalance: jest.fn(() => mockMarketAccountBalance),
}));
jest.mock('@apollo/client', () => ({
...jest.requireActual('@apollo/client'),
useQuery: jest.fn(() => ({ data: mockNotEmptyData })),
jest.mock('@vegaprotocol/positions', () => ({
...jest.requireActual('@vegaprotocol/positions'),
useMarketPositionOpenVolume: jest.fn(() => '100002'),
}));
describe('useOrderPosition Hook', () => {
@ -62,85 +25,28 @@ describe('useOrderPosition Hook', () => {
jest.clearAllMocks();
});
it('should return proper positive value', () => {
const { result } = renderHook(() =>
useMarketPositions({ marketId: 'marketId', partyId: 'partyId' })
const { result } = renderHook(
() => useMarketPositions({ marketId: 'marketId' }),
{ wrapper: MockedProvider }
);
expect(result.current?.openVolume.toNumber()).toEqual(100002);
expect(result.current?.balance.toString()).toEqual('50001000000');
expect(result.current?.openVolume).toEqual('100002');
expect(result.current?.balance).toEqual('50001000000');
});
it('if balance equal 0 return null', () => {
mockNotEmptyData = {
party: {
accountsConnection: {
edges: [
{
node: {
balance: '0',
asset: {
decimals: 5,
},
market: {
id: 'marketId',
},
},
},
],
},
positionsConnection: {
edges: [
{
node: {
openVolume: '2',
market: {
id: 'marketId',
},
},
},
],
},
},
};
const { result } = renderHook(() =>
useMarketPositions({ marketId: 'marketId', partyId: 'partyId' })
mockMarketAccountBalance = { accountBalance: '0', accountDecimals: 5 };
const { result } = renderHook(
() => useMarketPositions({ marketId: 'marketId' }),
{ wrapper: MockedProvider }
);
expect(result.current).toBeNull();
});
it('if no markets return null', () => {
mockNotEmptyData = {
party: {
accountsConnection: {
edges: [
{
node: {
balance: '33330',
asset: {
decimals: 5,
},
market: {
id: 'otherMarketId',
},
},
},
],
},
positionsConnection: {
edges: [
{
node: {
openVolume: '2',
market: {
id: 'otherMarketId',
},
},
},
],
},
},
};
const { result } = renderHook(() =>
useMarketPositions({ marketId: 'marketId', partyId: 'partyId' })
mockMarketAccountBalance = { accountBalance: '', accountDecimals: null };
const { result } = renderHook(
() => useMarketPositions({ marketId: 'marketId' }),
{ wrapper: MockedProvider }
);
expect(result.current).toBeNull();
});

View File

@ -1,48 +1,34 @@
import { useMemo } from 'react';
import { BigNumber } from 'bignumber.js';
import { useMarketPositionsQuery } from './__generated__/MarketPositions';
import { removePaginationWrapper } from '@vegaprotocol/react-helpers';
import { useMarketAccountBalance } from '@vegaprotocol/accounts';
import { useMarketPositionOpenVolume } from '@vegaprotocol/positions';
interface Props {
marketId: string;
partyId: string;
}
export type PositionMargin = {
openVolume: BigNumber;
balance: BigNumber;
openVolume: string;
balance: string;
balanceDecimals?: number;
} | null;
export const useMarketPositions = ({
marketId,
partyId,
}: Props): PositionMargin => {
const { data } = useMarketPositionsQuery({
pollInterval: 5000,
variables: { partyId },
fetchPolicy: 'no-cache',
});
export const useMarketPositions = ({ marketId }: Props): PositionMargin => {
const { accountBalance, accountDecimals } = useMarketAccountBalance(marketId);
const openVolume = useMarketPositionOpenVolume(marketId);
const accounts = removePaginationWrapper(
data?.party?.accountsConnection?.edges
);
const account = accounts.find((nodes) => nodes.market?.id === marketId);
if (account) {
const positionConnectionNode =
data?.party?.positionsConnection?.edges?.find(
(nodes) => nodes.node.market.id === marketId
);
const balance = new BigNumber(account.balance || 0);
const openVolume = new BigNumber(
positionConnectionNode?.node.openVolume || 0
);
if (!balance.isZero() && !openVolume.isZero()) {
return {
balance,
balanceDecimals: account?.asset.decimals,
openVolume,
};
return useMemo(() => {
if (accountBalance && accountDecimals) {
const balance = new BigNumber(accountBalance);
const volume = new BigNumber(openVolume);
if (!balance.isZero() && !volume.isZero()) {
return {
balance: accountBalance,
balanceDecimals: accountDecimals,
openVolume,
};
}
}
}
return null;
return null;
}, [accountBalance, accountDecimals, openVolume]);
};

View File

@ -1,31 +1,31 @@
import { renderHook } from '@testing-library/react';
import { MockedProvider } from '@apollo/client/testing';
import * as Schema from '@vegaprotocol/types';
import type { PositionMargin } from './use-market-positions';
import { BigNumber } from 'bignumber.js';
import { useMaximumPositionSize } from './use-maximum-position-size';
import type { AccountFragment as Account } from './__generated__/PartyBalance';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import type { PositionMargin } from './use-market-positions';
import { useMaximumPositionSize } from './use-maximum-position-size';
jest.mock('@vegaprotocol/wallet', () => ({
...jest.requireActual('@vegaprotocol/wallet'),
useVegaWallet: jest.fn().mockReturnValue('wallet-pub-key'),
}));
let mockAccountBalance: {
accountBalance: string;
accountDecimals: number | null;
} = { accountBalance: '200000', accountDecimals: 5 };
jest.mock('@vegaprotocol/accounts', () => ({
...jest.requireActual('@vegaprotocol/accounts'),
useAccountBalance: jest.fn(() => mockAccountBalance),
}));
const defaultMockMarketPositions = {
openVolume: new BigNumber(1),
balance: new BigNumber(100000),
openVolume: '1',
balance: '100000',
};
let mockMarketPositions: PositionMargin | null = defaultMockMarketPositions;
const mockAccount: Account = {
__typename: 'AccountBalance',
type: Schema.AccountType.ACCOUNT_TYPE_GENERAL,
balance: '200000',
asset: {
__typename: 'Asset',
id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
symbol: 'tBTC',
name: 'tBTC TEST',
decimals: 5,
},
};
const mockOrder: OrderSubmissionBody['orderSubmission'] = {
type: Schema.OrderType.TYPE_MARKET,
size: '1',
@ -34,12 +34,6 @@ const mockOrder: OrderSubmissionBody['orderSubmission'] = {
marketId: 'market-id',
};
jest.mock('./use-settlement-account', () => {
return {
useSettlementAccount: jest.fn(() => mockAccount),
};
});
jest.mock('./use-market-positions', () => ({
useMarketPositions: ({
marketId,
@ -55,15 +49,15 @@ describe('useMaximumPositionSize', () => {
mockMarketPositions = null;
const price = '50';
const expected = 4000;
const { result } = renderHook(() =>
useMaximumPositionSize({
marketId: '',
partyId: '',
price,
settlementAssetId: '',
order: mockOrder,
accounts: [mockAccount],
})
const { result } = renderHook(
() =>
useMaximumPositionSize({
marketId: '',
price,
settlementAssetId: '',
order: mockOrder,
}),
{ wrapper: MockedProvider }
);
expect(result.current).toBe(expected);
});
@ -72,15 +66,15 @@ describe('useMaximumPositionSize', () => {
const price = '50';
mockMarketPositions = defaultMockMarketPositions;
const expected = 3999;
const { result } = renderHook(() =>
useMaximumPositionSize({
marketId: '',
partyId: '',
price,
settlementAssetId: '',
order: mockOrder,
accounts: [mockAccount],
})
const { result } = renderHook(
() =>
useMaximumPositionSize({
marketId: '',
price,
settlementAssetId: '',
order: mockOrder,
}),
{ wrapper: MockedProvider }
);
expect(result.current).toBe(expected);
});
@ -90,33 +84,36 @@ describe('useMaximumPositionSize', () => {
mockOrder.side = Schema.Side.SIDE_SELL;
mockMarketPositions = defaultMockMarketPositions;
const expected = 4001;
const { result } = renderHook(() =>
useMaximumPositionSize({
marketId: '',
partyId: '',
price,
settlementAssetId: '',
order: mockOrder,
accounts: [mockAccount],
})
const { result } = renderHook(
() =>
useMaximumPositionSize({
marketId: '',
price,
settlementAssetId: '',
order: mockOrder,
}),
{ wrapper: MockedProvider }
);
expect(result.current).toBe(expected);
});
it('should return zero if no account balance', () => {
mockAccount.balance = '0';
mockAccountBalance = {
accountBalance: '0',
accountDecimals: 5,
};
const price = '50';
mockMarketPositions = defaultMockMarketPositions;
const expected = 0;
const { result } = renderHook(() =>
useMaximumPositionSize({
marketId: '',
partyId: '',
price,
settlementAssetId: '',
order: mockOrder,
accounts: [],
})
const { result } = renderHook(
() =>
useMaximumPositionSize({
marketId: '',
price,
settlementAssetId: '',
order: mockOrder,
}),
{ wrapper: MockedProvider }
);
expect(result.current).toBe(expected);
});

View File

@ -1,13 +1,10 @@
import { useMarketPositions } from './use-market-positions';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import { useSettlementAccount } from './use-settlement-account';
import * as Schema from '@vegaprotocol/types';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import { useAccountBalance } from '@vegaprotocol/accounts';
import { BigNumber } from 'bignumber.js';
import type { AccountFragment as Account } from './__generated__/PartyBalance';
import { useMarketPositions } from './use-market-positions';
interface Props {
partyId: string;
accounts: Account[];
marketId: string;
price?: string;
settlementAssetId: string;
@ -19,37 +16,26 @@ const getSize = (balance: string, price: string) =>
export const useMaximumPositionSize = ({
marketId,
accounts,
partyId,
price,
settlementAssetId,
order,
}: Props): number => {
const settlementAccount = useSettlementAccount(
settlementAssetId,
accounts,
Schema.AccountType.ACCOUNT_TYPE_GENERAL
);
const marketPositions = useMarketPositions({ marketId: marketId, partyId });
if (
!settlementAccount?.balance ||
new BigNumber(settlementAccount?.balance || 0).isZero()
) {
const { accountBalance } = useAccountBalance(settlementAssetId) || {};
const marketPositions = useMarketPositions({ marketId: marketId });
if (!accountBalance || new BigNumber(accountBalance || 0).isZero()) {
return 0;
}
const size = getSize(settlementAccount.balance, price || '');
const size = getSize(accountBalance, price || '');
if (!marketPositions) {
return size.toNumber() || 0;
}
const isSameSide =
(marketPositions.openVolume.isPositive() &&
(new BigNumber(marketPositions.openVolume).isPositive() &&
order.side === Schema.Side.SIDE_BUY) ||
(marketPositions.openVolume.isNegative() &&
(new BigNumber(marketPositions.openVolume).isNegative() &&
order.side === Schema.Side.SIDE_SELL);
const adjustedForVolume = new BigNumber(size)[isSameSide ? 'minus' : 'plus'](

View File

@ -1,15 +1,18 @@
import * as React from 'react';
import { renderHook } from '@testing-library/react';
import { MockedProvider } from '@apollo/client/testing';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import type { MarketDealTicket } from '@vegaprotocol/market-list';
import type { PartyBalanceQuery } from './__generated__/PartyBalance';
import { useOrderCloseOut } from './use-order-closeout';
jest.mock('@vegaprotocol/wallet', () => ({
...jest.requireActual('@vegaprotocol/wallet'),
useVegaWallet: jest.fn().mockReturnValue('wallet-pub-key'),
}));
let mockMarketMargin: string | undefined = undefined;
jest.mock('@vegaprotocol/positions', () => ({
...jest.requireActual('@vegaprotocol/positions'),
useMarketMargin: () => mockMarketMargin,
}));
describe('useOrderCloseOut', () => {
const order = { size: '2', side: 'SIDE_BUY' };
@ -29,43 +32,32 @@ describe('useOrderCloseOut', () => {
},
},
},
};
const partyData = {
party: {
accountsConnection: {
edges: [
{
node: {
balance: '200000',
asset: {
id: 'assetId',
decimals: 5,
},
},
},
],
},
data: {
markPrice: 100000,
},
};
} as unknown as MarketDealTicket;
beforeEach(() => {
jest.clearAllMocks();
});
it('should return proper null value', () => {
mockMarketMargin = '-1';
const { result } = renderHook(
() =>
useOrderCloseOut({
order: order as OrderSubmissionBody['orderSubmission'],
market: market as MarketDealTicket,
partyData: partyData as PartyBalanceQuery,
market: { ...market, data: { ...market.data, markPrice: '0' } },
}),
{
wrapper: ({ children }: { children: React.ReactNode }) => (
<MockedProvider mocks={[]}>{children}</MockedProvider>
),
wrapper: MockedProvider,
}
);
expect(result.current).toEqual(null);
});
it('should return proper sell value', () => {
mockMarketMargin = '0';
const { result } = renderHook(
() =>
useOrderCloseOut({
@ -73,13 +65,10 @@ describe('useOrderCloseOut', () => {
...order,
side: 'SIDE_SELL',
} as OrderSubmissionBody['orderSubmission'],
market: market as MarketDealTicket,
partyData: partyData as PartyBalanceQuery,
market: market,
}),
{
wrapper: ({ children }: { children: React.ReactNode }) => (
<MockedProvider mocks={[]}>{children}</MockedProvider>
),
wrapper: MockedProvider,
}
);
expect(result.current).toEqual('1.00');
@ -93,12 +82,10 @@ describe('useOrderCloseOut', () => {
...order,
side: 'SIDE_SELL',
} as OrderSubmissionBody['orderSubmission'],
market: market as MarketDealTicket,
market: { ...market, data: { ...market.data, markPrice: '0' } },
}),
{
wrapper: ({ children }: { children: React.ReactNode }) => (
<MockedProvider mocks={[]}>{children}</MockedProvider>
),
wrapper: MockedProvider,
}
);
expect(result.current).toEqual('0.00');

View File

@ -1,85 +1,47 @@
import { BigNumber } from 'bignumber.js';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import { useVegaWallet } from '@vegaprotocol/wallet';
import {
addDecimal,
formatNumber,
removePaginationWrapper,
} from '@vegaprotocol/react-helpers';
import { useMarketPositions } from './use-market-positions';
import { useMarketDataMarkPrice } from './use-market-data-mark-price';
import { usePartyMarketDataQuery } from './__generated__/PartyMarketData';
import { addDecimal, formatNumber } from '@vegaprotocol/react-helpers';
import * as Schema from '@vegaprotocol/types';
import type { PartyBalanceQuery } from './__generated__/PartyBalance';
import { useSettlementAccount } from './use-settlement-account';
import type { MarketDealTicket } from '@vegaprotocol/market-list';
import {
useAccountBalance,
useMarketAccountBalance,
} from '@vegaprotocol/accounts';
import { useMarketMargin } from '@vegaprotocol/positions';
import { useMarketPositions } from './use-market-positions';
interface Props {
order: OrderSubmissionBody['orderSubmission'];
market: MarketDealTicket;
partyData?: PartyBalanceQuery;
}
export const useOrderCloseOut = ({
order,
market,
partyData,
}: Props): string | null => {
const { pubKey } = useVegaWallet();
const accounts = removePaginationWrapper(
partyData?.party?.accountsConnection?.edges
export const useOrderCloseOut = ({ order, market }: Props): string | null => {
const { accountBalance, accountDecimals } = useAccountBalance(
market.tradableInstrument.instrument.product.settlementAsset.id
);
const account = useSettlementAccount(
market.tradableInstrument.instrument.product.settlementAsset.id,
accounts
);
const { data } = usePartyMarketDataQuery({
pollInterval: 5000,
variables: { partyId: pubKey || '' },
skip: !pubKey,
});
const markPriceData = useMarketDataMarkPrice(market.id);
const marketPositions = useMarketPositions({
marketId: market.id,
partyId: pubKey || '',
});
const { accountBalance: positionBalance, accountDecimals: positionDecimals } =
useMarketAccountBalance(market.id);
const maintenanceLevel = useMarketMargin(market.id);
const marginMaintenanceLevel = new BigNumber(
addDecimal(
data?.party?.marginsConnection?.edges?.find(
(nodes) => nodes.node.market.id === market.id
)?.node.maintenanceLevel || 0,
market.decimalPlaces
)
);
const dataAccounts = removePaginationWrapper(
data?.party?.accountsConnection?.edges
);
const positionAccount = dataAccounts.find(
(account) => account.market?.id === market.id
addDecimal(maintenanceLevel || 0, market.decimalPlaces)
);
const positionAccountBalance = new BigNumber(
addDecimal(
positionAccount?.balance || 0,
positionAccount?.asset?.decimals || 0
)
addDecimal(positionBalance || 0, positionDecimals || 0)
);
const generalAccountBalance = new BigNumber(
addDecimal(account?.balance || 0, account?.asset.decimals || 0)
addDecimal(accountBalance || 0, accountDecimals || 0)
);
const { openVolume } =
useMarketPositions({
marketId: market.id,
}) || {};
const volume = new BigNumber(
addDecimal(
marketPositions?.openVolume.toString() || '0',
market.positionDecimalPlaces
)
addDecimal(openVolume || '0', market.positionDecimalPlaces)
)[order.side === Schema.Side.SIDE_BUY ? 'plus' : 'minus'](order.size);
const markPrice = new BigNumber(
addDecimal(
markPriceData?.market?.data?.markPrice || 0,
markPriceData?.market?.decimalPlaces || 0
)
addDecimal(market.data.markPrice || 0, market.decimalPlaces || 0)
);
// regarding formula (marginMaintenanceLevel - positionAccountBalance - generalAccountBalance) / volume + markPrice
const marginDifference = marginMaintenanceLevel

View File

@ -1,7 +1,6 @@
import { useMemo } from 'react';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { toBigNum } from '@vegaprotocol/react-helpers';
import type { OrderMargin } from './use-order-margin';
import { useAccountBalance } from '@vegaprotocol/accounts';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import { useOrderMargin } from './use-order-margin';
@ -14,7 +13,7 @@ interface Props {
export const useOrderMarginValidation = ({ market, order }: Props) => {
const { pubKey } = useVegaWallet();
const estMargin: OrderMargin | null = useOrderMargin({
const estMargin = useOrderMargin({
order,
market,
partyId: pubKey || '',

View File

@ -26,8 +26,8 @@ jest.mock('@apollo/client', () => ({
}));
let mockMarketPositions: PositionMargin = {
openVolume: new BigNumber(1),
balance: new BigNumber(100000),
openVolume: '1',
balance: '100000',
};
jest.mock('./use-market-positions', () => ({

View File

@ -1,8 +1,8 @@
import { useMemo } from 'react';
import { BigNumber } from 'bignumber.js';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import { removeDecimal } from '@vegaprotocol/react-helpers';
import { useMarketPositions } from './use-market-positions';
import type { EstimateOrderQuery } from './__generated__/EstimateOrder';
import { useEstimateOrderQuery } from './__generated__/EstimateOrder';
import type { MarketDealTicket } from '@vegaprotocol/market-list';
import { getDerivedPrice } from '../utils/get-price';
@ -14,12 +14,6 @@ export interface Props {
derivedPrice?: string;
}
const addFees = (feeObj: EstimateOrderQuery['estimateOrder']['fee']) => {
return new BigNumber(feeObj.makerFee)
.plus(feeObj.liquidityFee)
.plus(feeObj.infrastructureFee);
};
export interface OrderMargin {
margin: string;
totalFees: string | null;
@ -36,7 +30,7 @@ export const useOrderMargin = ({
partyId,
derivedPrice,
}: Props): OrderMargin | null => {
const marketPositions = useMarketPositions({ marketId: market.id, partyId });
const { balance } = useMarketPositions({ marketId: market.id }) || {};
const priceForEstimate = derivedPrice || getDerivedPrice(order, market);
const { data } = useEstimateOrderQuery({
@ -51,29 +45,29 @@ export const useOrderMargin = ({
},
skip: !partyId || !market.id || !order.size || !priceForEstimate,
});
if (data?.estimateOrder.marginLevels.initialLevel) {
const fees =
data?.estimateOrder?.fee && addFees(data.estimateOrder.fee).toString();
const margin = BigNumber.maximum(
0,
new BigNumber(data.estimateOrder.marginLevels.initialLevel).minus(
marketPositions?.balance || 0
)
).toString();
const { makerFee, liquidityFee, infrastructureFee } =
data.estimateOrder.fee;
return {
margin,
totalFees: fees,
fees: {
makerFee,
liquidityFee,
infrastructureFee,
},
};
}
return null;
const { makerFee, liquidityFee, infrastructureFee } = data?.estimateOrder
.fee || { makerFee: '', liquidityFee: '', infrastructureFee: '' };
const { initialLevel } = data?.estimateOrder.marginLevels ?? {};
return useMemo(() => {
if (initialLevel) {
const margin = BigNumber.maximum(
0,
new BigNumber(initialLevel).minus(balance || 0)
).toString();
const fees = new BigNumber(makerFee)
.plus(liquidityFee)
.plus(infrastructureFee)
.toString();
return {
margin,
totalFees: fees,
fees: {
makerFee,
liquidityFee,
infrastructureFee,
},
};
}
return null;
}, [initialLevel, makerFee, liquidityFee, infrastructureFee, balance]);
};

View File

@ -1,90 +0,0 @@
import { renderHook } from '@testing-library/react';
import { useSettlementAccount } from './use-settlement-account';
import * as Schema from '@vegaprotocol/types';
import type { AccountFragment as Account } from './__generated__/PartyBalance';
describe('useSettlementAccount Hook', () => {
it('should filter accounts by settlementAssetId', () => {
const accounts: Account[] = [
{
__typename: 'AccountBalance',
type: Schema.AccountType.ACCOUNT_TYPE_GENERAL,
balance: '2000000000000000000000',
asset: {
__typename: 'Asset',
id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
symbol: 'tBTC',
name: 'tBTC TEST',
decimals: 5,
},
},
{
__typename: 'AccountBalance',
type: Schema.AccountType.ACCOUNT_TYPE_GENERAL,
balance: '1000000000',
asset: {
__typename: 'Asset',
id: '6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61',
symbol: 'tDAI',
name: 'tDAI TEST',
decimals: 5,
},
},
{
__typename: 'AccountBalance',
type: Schema.AccountType.ACCOUNT_TYPE_GENERAL,
balance: '5000000000000000000',
asset: {
__typename: 'Asset',
id: 'fc7fd956078fb1fc9db5c19b88f0874c4299b2a7639ad05a47a28c0aef291b55',
symbol: 'VEGA',
name: 'Vega (testnet)',
decimals: 18,
},
},
{
__typename: 'AccountBalance',
type: Schema.AccountType.ACCOUNT_TYPE_MARGIN,
balance: '5000000000000000000',
asset: {
__typename: 'Asset',
id: 'fc7fd956078fb1fc9db5c19b88f0874c4299b2a7639ad05a47a28c0aef291b55',
symbol: 'VEGA',
name: 'Vega (testnet)',
decimals: 18,
},
},
];
const tDAI =
'6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61';
const vega =
'fc7fd956078fb1fc9db5c19b88f0874c4299b2a7639ad05a47a28c0aef291b55';
const { result: resultDai } = renderHook(() =>
useSettlementAccount(tDAI, accounts)
);
expect(resultDai.current?.balance).toBe(accounts[1].balance);
expect(resultDai.current?.asset).toEqual(accounts[1].asset);
const { result: resultVega } = renderHook(() =>
useSettlementAccount(
vega,
accounts,
Schema.AccountType.ACCOUNT_TYPE_MARGIN
)
);
expect(resultVega.current?.balance).toBe(accounts[3].balance);
expect(resultVega.current?.asset).toEqual(accounts[3].asset);
});
it('should return null if no accounts', () => {
const accounts: Account[] = [];
const settlementAssetId =
'6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61';
const { result } = renderHook(() =>
useSettlementAccount(settlementAssetId, accounts)
);
expect(result.current).toBe(null);
});
});

View File

@ -1,20 +0,0 @@
import type * as Schema from '@vegaprotocol/types';
import { useMemo } from 'react';
import type { AccountFragment as Account } from './__generated__/PartyBalance';
export const useSettlementAccount = (
settlementAssetId: string,
accounts: Account[],
type?: Schema.AccountType
): Account | null => {
const callback = () =>
accounts.find((account) => {
if (type) {
return account.asset.id === settlementAssetId && account.type === type;
}
return account.asset.id === settlementAssetId;
});
const account = useMemo(callback, [accounts, settlementAssetId, type]);
return account || null;
};

View File

@ -4,3 +4,5 @@ export * from './lib/positions-data-providers';
export * from './lib/positions-table';
export * from './lib/use-close-position';
export * from './lib/use-positions-data';
export * from './lib/use-market-position-open-volume';
export * from './lib/use-market-margin';

View File

@ -0,0 +1,51 @@
import { useCallback, useMemo, useState } from 'react';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { useDataProvider } from '@vegaprotocol/react-helpers';
import { marginsDataProvider } from './margin-data-provider';
import type {
MarginsQuery,
MarginsSubscriptionSubscription,
} from './__generated__/Positions';
const getMarketMarginPosition = ({
data,
marketId,
}: {
data: MarginsQuery['party'] | null;
marketId: string;
}) => {
const positions =
data?.marginsConnection?.edges?.map((item) => item.node) ?? [];
return positions.find((item) => item.market.id === marketId);
};
export const useMarketMargin = (marketId: string) => {
const { pubKey } = useVegaWallet();
const [marginLevel, setMarginLevel] = useState<string>('');
const variables = useMemo(() => {
return { partyId: pubKey || '' };
}, [pubKey]);
const update = useCallback(
({ data }: { data: MarginsQuery['party'] | null }) => {
const marginMarketPosition = getMarketMarginPosition({ data, marketId });
if (marginLevel !== marginMarketPosition?.maintenanceLevel) {
setMarginLevel(marginMarketPosition?.maintenanceLevel || '');
}
return true;
},
[marginLevel, setMarginLevel, marketId]
);
useDataProvider<
MarginsQuery['party'],
MarginsSubscriptionSubscription['margins']
>({
dataProvider: marginsDataProvider,
variables,
skip: !pubKey || !marketId,
update,
});
return marginLevel;
};

View File

@ -0,0 +1,50 @@
import { useCallback, useMemo, useState } from 'react';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { positionsDataProvider } from './positions-data-providers';
import { useDataProvider } from '@vegaprotocol/react-helpers';
import type {
PositionsQuery,
PositionsSubscriptionSubscription,
} from './__generated__/Positions';
const getMarketPosition = ({
data,
marketId,
}: {
data: PositionsQuery['party'];
marketId: string;
}) => {
const positions =
data?.positionsConnection?.edges?.map((item) => item.node) ?? [];
return positions.find((item) => item.market.id === marketId);
};
export const useMarketPositionOpenVolume = (marketId: string) => {
const { pubKey } = useVegaWallet();
const [openVolume, setOpenVolume] = useState<string>('');
const variables = useMemo(() => {
return { partyId: pubKey || '' };
}, [pubKey]);
const update = useCallback(
({ data }: { data: PositionsQuery['party'] | undefined }) => {
const position = getMarketPosition({ data, marketId });
if (openVolume !== position?.openVolume) {
setOpenVolume(position?.openVolume || '');
}
return true;
},
[openVolume, setOpenVolume, marketId]
);
useDataProvider<
PositionsQuery['party'],
PositionsSubscriptionSubscription['positions']
>({
dataProvider: positionsDataProvider,
variables,
skip: !pubKey || !marketId,
update,
});
return openVolume;
};