diff --git a/apps/console-lite-e2e/src/integration/market-selector.test.ts b/apps/console-lite-e2e/src/integration/market-selector.test.ts index c64a9be03..f14c0780a 100644 --- a/apps/console-lite-e2e/src/integration/market-selector.test.ts +++ b/apps/console-lite-e2e/src/integration/market-selector.test.ts @@ -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()); }); diff --git a/apps/console-lite-e2e/src/integration/market-trade.test.ts b/apps/console-lite-e2e/src/integration/market-trade.test.ts index 1203ed474..2150eda2d 100644 --- a/apps/console-lite-e2e/src/integration/market-trade.test.ts +++ b/apps/console-lite-e2e/src/integration/market-trade.test.ts @@ -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(); diff --git a/apps/console-lite-e2e/src/integration/portfolio-page.test.ts b/apps/console-lite-e2e/src/integration/portfolio-page.test.ts index 85a0b005e..44d843309 100644 --- a/apps/console-lite-e2e/src/integration/portfolio-page.test.ts +++ b/apps/console-lite-e2e/src/integration/portfolio-page.test.ts @@ -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); }); }); diff --git a/apps/console-lite-e2e/src/support/mocks/generate-accounts.ts b/apps/console-lite-e2e/src/support/mocks/generate-accounts.ts index bde6eee4b..0ab88bc0a 100644 --- a/apps/console-lite-e2e/src/support/mocks/generate-accounts.ts +++ b/apps/console-lite-e2e/src/support/mocks/generate-accounts.ts @@ -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: { diff --git a/apps/console-lite-e2e/src/support/mocks/generate-market-depth.ts b/apps/console-lite-e2e/src/support/mocks/generate-market-depth.ts index feb726659..98d707e9a 100644 --- a/apps/console-lite-e2e/src/support/mocks/generate-market-depth.ts +++ b/apps/console-lite-e2e/src/support/mocks/generate-market-depth.ts @@ -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', diff --git a/apps/console-lite-e2e/src/support/mocks/generate-market-mark-price.ts b/apps/console-lite-e2e/src/support/mocks/generate-market-mark-price.ts deleted file mode 100644 index e16c43c7d..000000000 --- a/apps/console-lite-e2e/src/support/mocks/generate-market-mark-price.ts +++ /dev/null @@ -1,9 +0,0 @@ -export const generateMarketMarkPrice = () => { - return { - market: { - decimalPlaces: 5, - data: { markPrice: '692748', __typename: 'MarketData' }, - __typename: 'Market', - }, - }; -}; diff --git a/apps/console-lite-e2e/src/support/mocks/generate-market-positions.ts b/apps/console-lite-e2e/src/support/mocks/generate-market-positions.ts deleted file mode 100644 index 5e9c4683d..000000000 --- a/apps/console-lite-e2e/src/support/mocks/generate-market-positions.ts +++ /dev/null @@ -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', - }, - }; -}; diff --git a/apps/console-lite-e2e/src/support/mocks/generate-markets.ts b/apps/console-lite-e2e/src/support/mocks/generate-markets.ts index 6362b0cab..712e7064e 100644 --- a/apps/console-lite-e2e/src/support/mocks/generate-markets.ts +++ b/apps/console-lite-e2e/src/support/mocks/generate-markets.ts @@ -1392,12 +1392,15 @@ export const generatePositionsMarkets = () => { }; }; -export const generateMarket = (): MarketQuery => { - return { +export const generateMarket = ( + override?: PartialDeep +): MarketQuery => { + const defaultResult = { market: { ...singleMarket, }, }; + return merge(defaultResult, override); }; export const generateMarketData = (): MarketDataQuery => { diff --git a/apps/console-lite-e2e/src/support/mocks/generate-party-balance.ts b/apps/console-lite-e2e/src/support/mocks/generate-party-balance.ts deleted file mode 100644 index 2856ae858..000000000 --- a/apps/console-lite-e2e/src/support/mocks/generate-party-balance.ts +++ /dev/null @@ -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 => { - 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); -}; diff --git a/apps/console-lite-e2e/src/support/mocks/generate-party-market-data.ts b/apps/console-lite-e2e/src/support/mocks/generate-party-market-data.ts deleted file mode 100644 index 64278a817..000000000 --- a/apps/console-lite-e2e/src/support/mocks/generate-party-market-data.ts +++ /dev/null @@ -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', - }, - }; -}; diff --git a/apps/console-lite-e2e/src/support/mocks/generate-positions.ts b/apps/console-lite-e2e/src/support/mocks/generate-positions.ts index 4e327b901..4388dbc09 100644 --- a/apps/console-lite-e2e/src/support/mocks/generate-positions.ts +++ b/apps/console-lite-e2e/src/support/mocks/generate-positions.ts @@ -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', diff --git a/apps/console-lite/src/app/components/deal-ticket/PartyBalance.graphql b/apps/console-lite/src/app/components/deal-ticket/PartyBalance.graphql deleted file mode 100644 index e33300d18..000000000 --- a/apps/console-lite/src/app/components/deal-ticket/PartyBalance.graphql +++ /dev/null @@ -1,18 +0,0 @@ -query PartyBalanceQuery($partyId: ID!) { - party(id: $partyId) { - accountsConnection { - edges { - node { - type - balance - asset { - id - symbol - name - decimals - } - } - } - } - } -} diff --git a/apps/console-lite/src/app/components/deal-ticket/__generated__/PartyBalance.ts b/apps/console-lite/src/app/components/deal-ticket/__generated__/PartyBalance.ts deleted file mode 100644 index 14fe6e013..000000000 --- a/apps/console-lite/src/app/components/deal-ticket/__generated__/PartyBalance.ts +++ /dev/null @@ -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) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(PartyBalanceQueryDocument, options); - } -export function usePartyBalanceQueryLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(PartyBalanceQueryDocument, options); - } -export type PartyBalanceQueryQueryHookResult = ReturnType; -export type PartyBalanceQueryLazyQueryHookResult = ReturnType; -export type PartyBalanceQueryQueryResult = Apollo.QueryResult; \ No newline at end of file diff --git a/apps/console-lite/src/app/components/deal-ticket/deal-ticket-balance.spec.tsx b/apps/console-lite/src/app/components/deal-ticket/deal-ticket-balance.spec.tsx index 305ad0162..e542a7313 100644 --- a/apps/console-lite/src/app/components/deal-ticket/deal-ticket-balance.spec.tsx +++ b/apps/console-lite/src/app/components/deal-ticket/deal-ticket-balance.spec.tsx @@ -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( - + , + { wrapper: MockedProvider } ); expect(getByRole('complementary')).toHaveAccessibleName('tDAI Balance'); @@ -39,11 +40,8 @@ describe('DealTicketBalance', function () { it('should prompt to connect wallet', () => { const { getByText } = render( - + , + { wrapper: MockedProvider } ); expect( @@ -52,12 +50,10 @@ describe('DealTicketBalance', function () { }); it('should display zero balance', () => { + mockAccountBalance = { accountBalance: '', accountDecimals: null }; const { getByText } = render( - + , + { wrapper: MockedProvider } ); expect(getByText('No tDAI left to trade')).toBeInTheDocument(); diff --git a/apps/console-lite/src/app/components/deal-ticket/deal-ticket-balance.tsx b/apps/console-lite/src/app/components/deal-ticket/deal-ticket-balance.tsx index 4f3de37af..0d0bc09c1 100644 --- a/apps/console-lite/src/app/components/deal-ticket/deal-ticket-balance.tsx +++ b/apps/console-lite/src/app/components/deal-ticket/deal-ticket-balance.tsx @@ -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 = (

- {settlementAccount + {!settlementBalance.isZero() ? t(`${formattedNumber}`) : `No ${settlementAssetSymbol} left to trade`}

diff --git a/apps/console-lite/src/app/components/deal-ticket/deal-ticket-container.tsx b/apps/console-lite/src/app/components/deal-ticket/deal-ticket-container.tsx index a178ea548..aebd8a356 100644 --- a/apps/console-lite/src/app/components/deal-ticket/deal-ticket-container.tsx +++ b/apps/console-lite/src/app/components/deal-ticket/deal-ticket-container.tsx @@ -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 = ; if (marketId && data) { const balance = ( @@ -61,7 +45,6 @@ export const DealTicketContainer = () => { settlementAsset={ data.tradableInstrument.instrument.product?.settlementAsset } - accounts={accounts || []} isWalletConnected={!!pubKey} /> ); diff --git a/apps/console-lite/src/app/components/deal-ticket/deal-ticket-steps.tsx b/apps/console-lite/src/app/components/deal-ticket/deal-ticket-steps.tsx index 0c5962a22..d72a74f8c 100644 --- a/apps/console-lite/src/app/components/deal-ticket/deal-ticket-steps.tsx +++ b/apps/console-lite/src/app/components/deal-ticket/deal-ticket-steps.tsx @@ -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( diff --git a/apps/trading-e2e/src/integration/trading-deal-ticket.cy.ts b/apps/trading-e2e/src/integration/trading-deal-ticket.cy.ts index b5984715f..6e757e1af 100644 --- a/apps/trading-e2e/src/integration/trading-deal-ticket.cy.ts +++ b/apps/trading-e2e/src/integration/trading-deal-ticket.cy.ts @@ -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') diff --git a/apps/trading-e2e/src/support/mocks/generate-fees.ts b/apps/trading-e2e/src/support/mocks/generate-fees.ts index f22b9c10b..1edd959c2 100644 --- a/apps/trading-e2e/src/support/mocks/generate-fees.ts +++ b/apps/trading-e2e/src/support/mocks/generate-fees.ts @@ -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', - }, - }; -}; diff --git a/apps/trading-e2e/src/support/trading.ts b/apps/trading-e2e/src/support/trading.ts index 77440f4d0..c37d7f633 100644 --- a/apps/trading-e2e/src/support/trading.ts +++ b/apps/trading-e2e/src/support/trading.ts @@ -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()); }; diff --git a/libs/accounts/src/lib/get-market-account.ts b/libs/accounts/src/lib/get-market-account.ts new file mode 100644 index 000000000..5a85f9a61 --- /dev/null +++ b/libs/accounts/src/lib/get-market-account.ts @@ -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; diff --git a/libs/accounts/src/lib/index.ts b/libs/accounts/src/lib/index.ts index 0dff722bf..d3b35a103 100644 --- a/libs/accounts/src/lib/index.ts +++ b/libs/accounts/src/lib/index.ts @@ -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'; diff --git a/libs/accounts/src/lib/use-market-account-balance.tsx b/libs/accounts/src/lib/use-market-account-balance.tsx new file mode 100644 index 000000000..99b0e2cd2 --- /dev/null +++ b/libs/accounts/src/lib/use-market-account-balance.tsx @@ -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(''); + const [accountDecimals, setAccountDecimals] = useState(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] + ); +}; diff --git a/libs/deal-ticket/src/hooks/MarketMarkPrice.graphql b/libs/deal-ticket/src/hooks/MarketMarkPrice.graphql deleted file mode 100644 index 6cb4cb1b3..000000000 --- a/libs/deal-ticket/src/hooks/MarketMarkPrice.graphql +++ /dev/null @@ -1,11 +0,0 @@ -query MarketMarkPrice($marketId: ID!) { - market(id: $marketId) { - decimalPlaces - data { - markPrice - market { - id - } - } - } -} diff --git a/libs/deal-ticket/src/hooks/MarketPositions.graphql b/libs/deal-ticket/src/hooks/MarketPositions.graphql deleted file mode 100644 index e3ca70727..000000000 --- a/libs/deal-ticket/src/hooks/MarketPositions.graphql +++ /dev/null @@ -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 - } - } - } - } - } -} diff --git a/libs/deal-ticket/src/hooks/PartyBalance.graphql b/libs/deal-ticket/src/hooks/PartyBalance.graphql deleted file mode 100644 index 45deec829..000000000 --- a/libs/deal-ticket/src/hooks/PartyBalance.graphql +++ /dev/null @@ -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 - } -} diff --git a/libs/deal-ticket/src/hooks/PartyMarketData.graphql b/libs/deal-ticket/src/hooks/PartyMarketData.graphql deleted file mode 100644 index f1d3014f9..000000000 --- a/libs/deal-ticket/src/hooks/PartyMarketData.graphql +++ /dev/null @@ -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 - } - } - } - } -} diff --git a/libs/deal-ticket/src/hooks/__generated__/MarketMarkPrice.ts b/libs/deal-ticket/src/hooks/__generated__/MarketMarkPrice.ts deleted file mode 100644 index 2737dc89c..000000000 --- a/libs/deal-ticket/src/hooks/__generated__/MarketMarkPrice.ts +++ /dev/null @@ -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) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(MarketMarkPriceDocument, options); - } -export function useMarketMarkPriceLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(MarketMarkPriceDocument, options); - } -export type MarketMarkPriceQueryHookResult = ReturnType; -export type MarketMarkPriceLazyQueryHookResult = ReturnType; -export type MarketMarkPriceQueryResult = Apollo.QueryResult; \ No newline at end of file diff --git a/libs/deal-ticket/src/hooks/__generated__/MarketPositions.ts b/libs/deal-ticket/src/hooks/__generated__/MarketPositions.ts deleted file mode 100644 index 6a6556956..000000000 --- a/libs/deal-ticket/src/hooks/__generated__/MarketPositions.ts +++ /dev/null @@ -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) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(MarketPositionsDocument, options); - } -export function useMarketPositionsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(MarketPositionsDocument, options); - } -export type MarketPositionsQueryHookResult = ReturnType; -export type MarketPositionsLazyQueryHookResult = ReturnType; -export type MarketPositionsQueryResult = Apollo.QueryResult; \ No newline at end of file diff --git a/libs/deal-ticket/src/hooks/__generated__/PartyBalance.ts b/libs/deal-ticket/src/hooks/__generated__/PartyBalance.ts deleted file mode 100644 index 8b4991521..000000000 --- a/libs/deal-ticket/src/hooks/__generated__/PartyBalance.ts +++ /dev/null @@ -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) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(PartyBalanceDocument, options); - } -export function usePartyBalanceLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(PartyBalanceDocument, options); - } -export type PartyBalanceQueryHookResult = ReturnType; -export type PartyBalanceLazyQueryHookResult = ReturnType; -export type PartyBalanceQueryResult = Apollo.QueryResult; \ No newline at end of file diff --git a/libs/deal-ticket/src/hooks/__generated__/PartyMarketData.ts b/libs/deal-ticket/src/hooks/__generated__/PartyMarketData.ts deleted file mode 100644 index 768ffced4..000000000 --- a/libs/deal-ticket/src/hooks/__generated__/PartyMarketData.ts +++ /dev/null @@ -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) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(PartyMarketDataDocument, options); - } -export function usePartyMarketDataLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(PartyMarketDataDocument, options); - } -export type PartyMarketDataQueryHookResult = ReturnType; -export type PartyMarketDataLazyQueryHookResult = ReturnType; -export type PartyMarketDataQueryResult = Apollo.QueryResult; \ No newline at end of file diff --git a/libs/deal-ticket/src/hooks/index.ts b/libs/deal-ticket/src/hooks/index.ts index a76bf58c3..1286c9075 100644 --- a/libs/deal-ticket/src/hooks/index.ts +++ b/libs/deal-ticket/src/hooks/index.ts @@ -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'; diff --git a/libs/deal-ticket/src/hooks/use-fee-deal-ticket-details.tsx b/libs/deal-ticket/src/hooks/use-fee-deal-ticket-details.tsx index 9b8430aa4..3bb27a0d4 100644 --- a/libs/deal-ticket/src/hooks/use-fee-deal-ticket-details.tsx +++ b/libs/deal-ticket/src/hooks/use-fee-deal-ticket-details.tsx @@ -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, ]); }; diff --git a/libs/deal-ticket/src/hooks/use-market-data-mark-price.ts b/libs/deal-ticket/src/hooks/use-market-data-mark-price.ts deleted file mode 100644 index 089a7779c..000000000 --- a/libs/deal-ticket/src/hooks/use-market-data-mark-price.ts +++ /dev/null @@ -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(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]); -}; diff --git a/libs/deal-ticket/src/hooks/use-market-positions.spec.ts b/libs/deal-ticket/src/hooks/use-market-positions.spec.ts index b8fb1aad3..6e6f3c4b1 100644 --- a/libs/deal-ticket/src/hooks/use-market-positions.spec.ts +++ b/libs/deal-ticket/src/hooks/use-market-positions.spec.ts @@ -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(); }); diff --git a/libs/deal-ticket/src/hooks/use-market-positions.ts b/libs/deal-ticket/src/hooks/use-market-positions.ts index b5c390e8b..4430c81f9 100644 --- a/libs/deal-ticket/src/hooks/use-market-positions.ts +++ b/libs/deal-ticket/src/hooks/use-market-positions.ts @@ -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]); }; diff --git a/libs/deal-ticket/src/hooks/use-maximum-position-size.spec.ts b/libs/deal-ticket/src/hooks/use-maximum-position-size.spec.ts index bcc753e6c..74b4a0a5a 100644 --- a/libs/deal-ticket/src/hooks/use-maximum-position-size.spec.ts +++ b/libs/deal-ticket/src/hooks/use-maximum-position-size.spec.ts @@ -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); }); diff --git a/libs/deal-ticket/src/hooks/use-maximum-position-size.ts b/libs/deal-ticket/src/hooks/use-maximum-position-size.ts index f5809b7aa..5981d782f 100644 --- a/libs/deal-ticket/src/hooks/use-maximum-position-size.ts +++ b/libs/deal-ticket/src/hooks/use-maximum-position-size.ts @@ -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']( diff --git a/libs/deal-ticket/src/hooks/use-order-closeout.spec.tsx b/libs/deal-ticket/src/hooks/use-order-closeout.spec.tsx index 430bcd48e..cf6508357 100644 --- a/libs/deal-ticket/src/hooks/use-order-closeout.spec.tsx +++ b/libs/deal-ticket/src/hooks/use-order-closeout.spec.tsx @@ -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 }) => ( - {children} - ), + 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 }) => ( - {children} - ), + 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 }) => ( - {children} - ), + wrapper: MockedProvider, } ); expect(result.current).toEqual('0.00'); diff --git a/libs/deal-ticket/src/hooks/use-order-closeout.ts b/libs/deal-ticket/src/hooks/use-order-closeout.ts index d2bf883aa..72d183a97 100644 --- a/libs/deal-ticket/src/hooks/use-order-closeout.ts +++ b/libs/deal-ticket/src/hooks/use-order-closeout.ts @@ -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 diff --git a/libs/deal-ticket/src/hooks/use-order-margin-validation.ts b/libs/deal-ticket/src/hooks/use-order-margin-validation.ts index b46040e4b..5d71aad6f 100644 --- a/libs/deal-ticket/src/hooks/use-order-margin-validation.ts +++ b/libs/deal-ticket/src/hooks/use-order-margin-validation.ts @@ -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 || '', diff --git a/libs/deal-ticket/src/hooks/use-order-margin.spec.ts b/libs/deal-ticket/src/hooks/use-order-margin.spec.ts index b05245abf..780e3d4af 100644 --- a/libs/deal-ticket/src/hooks/use-order-margin.spec.ts +++ b/libs/deal-ticket/src/hooks/use-order-margin.spec.ts @@ -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', () => ({ diff --git a/libs/deal-ticket/src/hooks/use-order-margin.ts b/libs/deal-ticket/src/hooks/use-order-margin.ts index e8cac1caa..67058a8d9 100644 --- a/libs/deal-ticket/src/hooks/use-order-margin.ts +++ b/libs/deal-ticket/src/hooks/use-order-margin.ts @@ -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]); }; diff --git a/libs/deal-ticket/src/hooks/use-settlement-account.spec.tsx b/libs/deal-ticket/src/hooks/use-settlement-account.spec.tsx deleted file mode 100644 index f443533f9..000000000 --- a/libs/deal-ticket/src/hooks/use-settlement-account.spec.tsx +++ /dev/null @@ -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); - }); -}); diff --git a/libs/deal-ticket/src/hooks/use-settlement-account.ts b/libs/deal-ticket/src/hooks/use-settlement-account.ts deleted file mode 100644 index 9ab8b2510..000000000 --- a/libs/deal-ticket/src/hooks/use-settlement-account.ts +++ /dev/null @@ -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; -}; diff --git a/libs/positions/src/index.ts b/libs/positions/src/index.ts index 80a5ae96b..057a1f978 100644 --- a/libs/positions/src/index.ts +++ b/libs/positions/src/index.ts @@ -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'; diff --git a/libs/positions/src/lib/use-market-margin.tsx b/libs/positions/src/lib/use-market-margin.tsx new file mode 100644 index 000000000..d2aeaf300 --- /dev/null +++ b/libs/positions/src/lib/use-market-margin.tsx @@ -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(''); + 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; +}; diff --git a/libs/positions/src/lib/use-market-position-open-volume.tsx b/libs/positions/src/lib/use-market-position-open-volume.tsx new file mode 100644 index 000000000..449625805 --- /dev/null +++ b/libs/positions/src/lib/use-market-position-open-volume.tsx @@ -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(''); + 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; +};