feat(console-lite): add trade balance component and hook (#516)

* feat(console-lite): add trade balance component and hook

* feat(console-lite): review fixes

Co-authored-by: Dexter <dexter.edwards93@gmail.com>
This commit is contained in:
Elmar 2022-06-10 14:55:14 +01:00 committed by GitHub
parent d0452aeb81
commit fde5149912
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 261 additions and 0 deletions

View File

@ -0,0 +1,59 @@
/* tslint:disable */
/* eslint-disable */
// @generated
// This file was automatically generated and should not be edited.
// ====================================================
// GraphQL query operation: PartyBalanceQuery
// ====================================================
export interface PartyBalanceQuery_party_accounts_asset {
__typename: "Asset";
/**
* The id of the asset
*/
id: string;
/**
* The symbol of the asset (e.g: GBP)
*/
symbol: string;
/**
* The full name of the asset (e.g: Great British Pound)
*/
name: string;
/**
* The precision of the asset
*/
decimals: number;
}
export interface PartyBalanceQuery_party_accounts {
__typename: "Account";
/**
* Balance as string - current account balance (approx. as balances can be updated several times per second)
*/
balance: string;
/**
* Asset, the 'currency'
*/
asset: PartyBalanceQuery_party_accounts_asset;
}
export interface PartyBalanceQuery_party {
__typename: "Party";
/**
* Collateral accounts relating to a party
*/
accounts: PartyBalanceQuery_party_accounts[] | null;
}
export interface PartyBalanceQuery {
/**
* An entity that is trading on the VEGA network
*/
party: PartyBalanceQuery_party | null;
}
export interface PartyBalanceQueryVariables {
partyId: string;
}

View File

@ -0,0 +1,55 @@
import * as React from 'react';
import type { DealTicketQuery_market_tradableInstrument_instrument_product_settlementAsset } from '@vegaprotocol/deal-ticket';
import type { PartyBalanceQuery_party_accounts } from './__generated__/PartyBalanceQuery';
import { useSettlementAccount } from '../../hooks/use-settlement-account';
import { addDecimalsFormatNumber, t } from '@vegaprotocol/react-helpers';
interface DealTicketBalanceProps {
settlementAsset: DealTicketQuery_market_tradableInstrument_instrument_product_settlementAsset;
accounts: PartyBalanceQuery_party_accounts[];
isWalletConnected: boolean;
}
export const DealTicketBalance = ({
settlementAsset,
accounts,
isWalletConnected,
}: DealTicketBalanceProps) => {
const settlementAssetId = settlementAsset?.id;
const settlementAssetSymbol = settlementAsset?.symbol;
const settlementAccount = useSettlementAccount(settlementAssetId, accounts);
const formatedNumber =
settlementAccount?.balance &&
settlementAccount.asset.decimals &&
addDecimalsFormatNumber(
settlementAccount.balance,
settlementAccount.asset.decimals
);
const balance = settlementAccount ? (
<p>
{t(
`${formatedNumber} ${settlementAccount.asset.symbol} available to trade`
)}
</p>
) : (
<p>{t(`You have no ${settlementAssetSymbol} available to trade`)}</p>
);
const connectWallet = (
<p>
{t(
"Please connect your Vega wallet to see your balance for this market's settlement asset"
)}
</p>
);
return (
<div className="text-right">
<div className="border border-current p-16 inline-block">
<small className="text-text">{t('Balance')}</small>
{isWalletConnected ? balance : connectWallet}
</div>
</div>
);
};

View File

@ -4,15 +4,58 @@ import {
DealTicketContainer as Container,
} from '@vegaprotocol/deal-ticket';
import { DealTicketSteps } from './deal-ticket-steps';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { gql, useQuery } from '@apollo/client';
import { DealTicketBalance } from './deal-ticket-balance';
import * as React from 'react';
import type { PartyBalanceQuery } from './__generated__/PartyBalanceQuery';
const tempEmptyText = <p>Please select a market from the markets page</p>;
const PARTY_BALANCE_QUERY = gql`
query PartyBalanceQuery($partyId: ID!) {
party(id: $partyId) {
accounts {
balance
asset {
id
symbol
name
decimals
}
}
}
}
`;
export const DealTicketContainer = () => {
const { marketId } = useParams<{ marketId: string }>();
const { keypair } = useVegaWallet();
const { data: partyData, loading } = useQuery<PartyBalanceQuery>(
PARTY_BALANCE_QUERY,
{
variables: { partyId: keypair?.pub },
skip: !keypair?.pub,
}
);
return marketId ? (
<Container marketId={marketId}>
{(data) => (
<DealTicketManager market={data.market}>
{loading ? (
'Loading...'
) : (
<DealTicketBalance
settlementAsset={
data.market.tradableInstrument.instrument.product
?.settlementAsset
}
accounts={partyData?.party?.accounts || []}
isWalletConnected={!!keypair?.pub}
/>
)}
<DealTicketSteps market={data.market} />
</DealTicketManager>
)}

View File

@ -0,0 +1,61 @@
import { renderHook } from '@testing-library/react-hooks';
import { useSettlementAccount } from './use-settlement-account';
import type { PartyBalanceQuery_party_accounts } from '../components/deal-ticket/__generated__/PartyBalanceQuery';
describe('useSettlementAccount Hook', () => {
it('should filter accounts by settlementAssetId', () => {
const accounts: PartyBalanceQuery_party_accounts[] = [
{
__typename: 'Account',
balance: '2000000000000000000000',
asset: {
__typename: 'Asset',
id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
symbol: 'tBTC',
name: 'tBTC TEST',
decimals: 5,
},
},
{
__typename: 'Account',
balance: '1000000000',
asset: {
__typename: 'Asset',
id: '6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61',
symbol: 'tDAI',
name: 'tDAI TEST',
decimals: 5,
},
},
{
__typename: 'Account',
balance: '5000000000000000000',
asset: {
__typename: 'Asset',
id: 'fc7fd956078fb1fc9db5c19b88f0874c4299b2a7639ad05a47a28c0aef291b55',
symbol: 'VEGA',
name: 'Vega (testnet)',
decimals: 18,
},
},
];
const settlementAssetId =
'6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61';
const { result } = renderHook(() =>
useSettlementAccount(settlementAssetId, accounts)
);
expect(result.current?.balance).toBe(accounts[1].balance);
expect(result.current?.asset).toEqual(accounts[1].asset);
});
it('should return null if no accounts', () => {
const accounts: PartyBalanceQuery_party_accounts[] = [];
const settlementAssetId =
'6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61';
const { result } = renderHook(() =>
useSettlementAccount(settlementAssetId, accounts)
);
expect(result.current).toBe(undefined);
});
});

View File

@ -0,0 +1,12 @@
import type { PartyBalanceQuery_party_accounts } from '../components/deal-ticket/__generated__/PartyBalanceQuery';
import { useMemo } from 'react';
export const useSettlementAccount = (
settlementAssetId: string,
accounts: PartyBalanceQuery_party_accounts[]
): PartyBalanceQuery_party_accounts | null => {
const callback = () =>
accounts.find((account) => account.asset.id === settlementAssetId);
const account = useMemo(callback, [accounts, settlementAssetId]);
return account as PartyBalanceQuery_party_accounts;
};

View File

@ -18,6 +18,12 @@ export const generateDealTicketQuery = (
instrument: {
product: {
quoteName: 'BTC',
settlementAsset: {
__typename: 'Asset',
id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
symbol: 'tBTC',
name: 'tBTC TEST',
},
__typename: 'Future',
},
__typename: 'Instrument',

View File

@ -9,12 +9,32 @@ import { MarketState, MarketTradingMode } from "@vegaprotocol/types";
// GraphQL query operation: DealTicketQuery
// ====================================================
export interface DealTicketQuery_market_tradableInstrument_instrument_product_settlementAsset {
__typename: "Asset";
/**
* The id of the asset
*/
id: string;
/**
* The symbol of the asset (e.g: GBP)
*/
symbol: string;
/**
* The full name of the asset (e.g: Great British Pound)
*/
name: string;
}
export interface DealTicketQuery_market_tradableInstrument_instrument_product {
__typename: "Future";
/**
* String representing the quote (e.g. BTCUSD -> USD is quote)
*/
quoteName: string;
/**
* The name of the asset (string)
*/
settlementAsset: DealTicketQuery_market_tradableInstrument_instrument_product_settlementAsset;
}
export interface DealTicketQuery_market_tradableInstrument_instrument {

View File

@ -21,6 +21,11 @@ const DEAL_TICKET_QUERY = gql`
product {
... on Future {
quoteName
settlementAsset {
id
symbol
name
}
}
}
}