Compare commits

...
Author SHA1 Message Date
Bartłomiej Głownia cfe083cbee feat(trading): margin mode selector 2024-01-05 13:54:53 +01:00
13 changed files with 361 additions and 27 deletions
+6
View File
@@ -3,6 +3,9 @@ fragment MarginFields on MarginLevels {
searchLevel
initialLevel
collateralReleaseLevel
marginFactor
marginMode
orderMarginLevel
asset {
id
}
@@ -33,6 +36,9 @@ subscription MarginsSubscription($partyId: ID!) {
searchLevel
initialLevel
collateralReleaseLevel
marginFactor
marginMode
orderMarginLevel
timestamp
}
}
+9 -3
View File
@@ -3,21 +3,21 @@ import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type MarginFieldsFragment = { __typename?: 'MarginLevels', maintenanceLevel: string, searchLevel: string, initialLevel: string, collateralReleaseLevel: string, asset: { __typename?: 'Asset', id: string }, market: { __typename?: 'Market', id: string } };
export type MarginFieldsFragment = { __typename?: 'MarginLevels', maintenanceLevel: string, searchLevel: string, initialLevel: string, collateralReleaseLevel: string, marginFactor: string, marginMode: Types.MarginMode, orderMarginLevel: string, asset: { __typename?: 'Asset', id: string }, market: { __typename?: 'Market', id: string } };
export type MarginsQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
}>;
export type MarginsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, marginsConnection?: { __typename?: 'MarginConnection', edges?: Array<{ __typename?: 'MarginEdge', node: { __typename?: 'MarginLevels', maintenanceLevel: string, searchLevel: string, initialLevel: string, collateralReleaseLevel: string, asset: { __typename?: 'Asset', id: string }, market: { __typename?: 'Market', id: string } } }> | null } | null } | null };
export type MarginsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, marginsConnection?: { __typename?: 'MarginConnection', edges?: Array<{ __typename?: 'MarginEdge', node: { __typename?: 'MarginLevels', maintenanceLevel: string, searchLevel: string, initialLevel: string, collateralReleaseLevel: string, marginFactor: string, marginMode: Types.MarginMode, orderMarginLevel: string, asset: { __typename?: 'Asset', id: string }, market: { __typename?: 'Market', id: string } } }> | null } | null } | null };
export type MarginsSubscriptionSubscriptionVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
}>;
export type MarginsSubscriptionSubscription = { __typename?: 'Subscription', margins: { __typename?: 'MarginLevelsUpdate', marketId: string, asset: string, partyId: string, maintenanceLevel: string, searchLevel: string, initialLevel: string, collateralReleaseLevel: string, timestamp: any } };
export type MarginsSubscriptionSubscription = { __typename?: 'Subscription', margins: { __typename?: 'MarginLevelsUpdate', marketId: string, asset: string, partyId: string, maintenanceLevel: string, searchLevel: string, initialLevel: string, collateralReleaseLevel: string, marginFactor: string, marginMode: Types.MarginMode, orderMarginLevel: string, timestamp: any } };
export const MarginFieldsFragmentDoc = gql`
fragment MarginFields on MarginLevels {
@@ -25,6 +25,9 @@ export const MarginFieldsFragmentDoc = gql`
searchLevel
initialLevel
collateralReleaseLevel
marginFactor
marginMode
orderMarginLevel
asset {
id
}
@@ -85,6 +88,9 @@ export const MarginsSubscriptionDocument = gql`
searchLevel
initialLevel
collateralReleaseLevel
marginFactor
marginMode
orderMarginLevel
timestamp
}
}
@@ -40,6 +40,9 @@ const update = (
searchLevel: delta.searchLevel,
initialLevel: delta.initialLevel,
collateralReleaseLevel: delta.collateralReleaseLevel,
marginFactor: delta.marginFactor,
marginMode: delta.marginMode,
orderMarginLevel: delta.orderMarginLevel,
asset: {
__typename: 'Asset',
id: delta.asset,
@@ -13,6 +13,7 @@ import { AsyncRendererInline } from '@vegaprotocol/ui-toolkit';
import { DealTicket } from './deal-ticket';
import { useFeatureFlags } from '@vegaprotocol/environment';
import { useT } from '../../use-t';
import { MarginModeSelector } from './margin-mode-selector';
interface DealTicketContainerProps {
marketId: string;
@@ -51,21 +52,26 @@ export const DealTicketContainer = ({
reload={reload}
>
{market && marketData ? (
featureFlags.STOP_ORDERS && showStopOrder ? (
<StopOrder
market={market}
marketPrice={marketPrice}
submit={(stopOrdersSubmission) => create({ stopOrdersSubmission })}
/>
) : (
<DealTicket
{...props}
market={market}
marketPrice={marketPrice}
marketData={marketData}
submit={(orderSubmission) => create({ orderSubmission })}
/>
)
<>
<MarginModeSelector marketId={marketId} />
{featureFlags.STOP_ORDERS && showStopOrder ? (
<StopOrder
market={market}
marketPrice={marketPrice}
submit={(stopOrdersSubmission) =>
create({ stopOrdersSubmission })
}
/>
) : (
<DealTicket
{...props}
market={market}
marketPrice={marketPrice}
marketData={marketData}
submit={(orderSubmission) => create({ orderSubmission })}
/>
)}
</>
) : (
<p>{t('Could not load market')}</p>
)}
@@ -0,0 +1,66 @@
import { useDataProvider } from '@vegaprotocol/data-provider';
import { Intent, TradingButton } from '@vegaprotocol/ui-toolkit';
import { marginModeDataProvider } from '@vegaprotocol/positions';
import { MarginMode, useVegaWallet } from '@vegaprotocol/wallet';
import * as Types from '@vegaprotocol/types';
import { useVegaTransactionStore } from '@vegaprotocol/web3';
export const MarginModeSelector = ({ marketId }: { marketId: string }) => {
const { pubKey, isReadOnly } = useVegaWallet();
const { data: marginMode } = useDataProvider({
dataProvider: marginModeDataProvider,
variables: {
partyId: pubKey || '',
marketId,
},
skip: !pubKey,
});
const create = useVegaTransactionStore((state) => state.create);
const disabled = isReadOnly;
return (
<div className="grid grid-cols-2 gap-2 mb-2">
<TradingButton
disabled={disabled}
size="extra-small"
onClick={() =>
create({
updateMarginMode: {
market_id: marketId,
mode: MarginMode.MARGIN_MODE_CROSS_MARGIN,
},
})
}
intent={
!marginMode ||
marginMode.marginMode === Types.MarginMode.MARGIN_MODE_CROSS_MARGIN
? Intent.Primary
: Intent.None
}
>
Cross
</TradingButton>
<TradingButton
disabled={disabled}
size="extra-small"
onClick={() =>
create({
updateMarginMode: {
market_id: marketId,
mode: MarginMode.MARGIN_MODE_ISOLATED_MARGIN,
marginFactor: '0.1',
},
})
}
intent={
marginMode?.marginMode ===
Types.MarginMode.MARGIN_MODE_ISOLATED_MARGIN
? Intent.Primary
: Intent.None
}
>
Isolated {marginMode?.margin_factor || '10'}x
</TradingButton>
</div>
);
};
+1
View File
@@ -1,4 +1,5 @@
export * from './lib/__generated__/Positions';
export * from './lib/margin-modes-provider';
export * from './lib/positions-data-providers';
export * from './lib/positions-table';
export * from './lib/positions-manager';
+20
View File
@@ -83,3 +83,23 @@ query EstimatePosition(
}
}
}
fragment MarginMode on PartyMarginMode {
marketId
partyId
marginMode
margin_factor
min_theoretical_margin_factor
max_theoretical_leverage
atEpoch
}
query MarginModes($partyId: ID!) {
partyMarginModes(partyId: $partyId) {
edges {
node {
...MarginMode
}
}
}
}
+60 -1
View File
@@ -29,6 +29,15 @@ export type EstimatePositionQueryVariables = Types.Exact<{
export type EstimatePositionQuery = { __typename?: 'Query', estimatePosition?: { __typename?: 'PositionEstimate', margin: { __typename?: 'MarginEstimate', worstCase: { __typename?: 'MarginLevels', maintenanceLevel: string, searchLevel: string, initialLevel: string, collateralReleaseLevel: string }, bestCase: { __typename?: 'MarginLevels', maintenanceLevel: string, searchLevel: string, initialLevel: string, collateralReleaseLevel: string } }, liquidation?: { __typename?: 'LiquidationEstimate', worstCase: { __typename?: 'LiquidationPrice', open_volume_only: string, including_buy_orders: string, including_sell_orders: string }, bestCase: { __typename?: 'LiquidationPrice', open_volume_only: string, including_buy_orders: string, including_sell_orders: string } } | null } | null };
export type MarginModeFragment = { __typename?: 'PartyMarginMode', marketId: string, partyId: string, marginMode: Types.MarginMode, margin_factor?: string | null, min_theoretical_margin_factor?: string | null, max_theoretical_leverage?: string | null, atEpoch: number };
export type MarginModesQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
}>;
export type MarginModesQuery = { __typename?: 'Query', partyMarginModes?: { __typename?: 'PartyMarginModesConnection', edges?: Array<{ __typename?: 'PartyMarginModeEdge', node: { __typename?: 'PartyMarginMode', marketId: string, partyId: string, marginMode: Types.MarginMode, margin_factor?: string | null, min_theoretical_margin_factor?: string | null, max_theoretical_leverage?: string | null, atEpoch: number } } | null> | null } | null };
export const PositionFieldsFragmentDoc = gql`
fragment PositionFields on Position {
realisedPNL
@@ -46,6 +55,17 @@ export const PositionFieldsFragmentDoc = gql`
}
}
`;
export const MarginModeFragmentDoc = gql`
fragment MarginMode on PartyMarginMode {
marketId
partyId
marginMode
margin_factor
min_theoretical_margin_factor
max_theoretical_leverage
atEpoch
}
`;
export const PositionsDocument = gql`
query Positions($partyIds: [ID!]!) {
positions(filter: {partyIds: $partyIds}) {
@@ -191,4 +211,43 @@ export function useEstimatePositionLazyQuery(baseOptions?: Apollo.LazyQueryHookO
}
export type EstimatePositionQueryHookResult = ReturnType<typeof useEstimatePositionQuery>;
export type EstimatePositionLazyQueryHookResult = ReturnType<typeof useEstimatePositionLazyQuery>;
export type EstimatePositionQueryResult = Apollo.QueryResult<EstimatePositionQuery, EstimatePositionQueryVariables>;
export type EstimatePositionQueryResult = Apollo.QueryResult<EstimatePositionQuery, EstimatePositionQueryVariables>;
export const MarginModesDocument = gql`
query MarginModes($partyId: ID!) {
partyMarginModes(partyId: $partyId) {
edges {
node {
...MarginMode
}
}
}
}
${MarginModeFragmentDoc}`;
/**
* __useMarginModesQuery__
*
* To run a query within a React component, call `useMarginModesQuery` and pass it any options that fit your needs.
* When your component renders, `useMarginModesQuery` 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 } = useMarginModesQuery({
* variables: {
* partyId: // value for 'partyId'
* },
* });
*/
export function useMarginModesQuery(baseOptions: Apollo.QueryHookOptions<MarginModesQuery, MarginModesQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<MarginModesQuery, MarginModesQueryVariables>(MarginModesDocument, options);
}
export function useMarginModesLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<MarginModesQuery, MarginModesQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<MarginModesQuery, MarginModesQueryVariables>(MarginModesDocument, options);
}
export type MarginModesQueryHookResult = ReturnType<typeof useMarginModesQuery>;
export type MarginModesLazyQueryHookResult = ReturnType<typeof useMarginModesLazyQuery>;
export type MarginModesQueryResult = Apollo.QueryResult<MarginModesQuery, MarginModesQueryVariables>;
@@ -0,0 +1,38 @@
import { removePaginationWrapper } from '@vegaprotocol/utils';
import {
makeDataProvider,
makeDerivedDataProvider,
} from '@vegaprotocol/data-provider';
import {
MarginModesDocument,
type MarginModesQueryVariables,
MarginModesQuery,
MarginModeFragment,
} from './__generated__/Positions';
export const marginModesDataProvider = makeDataProvider<
MarginModesQuery,
MarginModeFragment[],
never,
never,
MarginModesQueryVariables
>({
query: MarginModesDocument,
getData: (responseData: MarginModesQuery | null) =>
removePaginationWrapper(responseData?.partyMarginModes?.edges) || [],
});
export const marginModeDataProvider = makeDerivedDataProvider<
MarginModeFragment | undefined,
never,
MarginModesQueryVariables & { marketId: string }
>(
[
(callback, client, variables) =>
marginModesDataProvider(callback, client, { partyId: variables.partyId }),
],
(data, variables) =>
(data as MarginModeFragment[]).find(
(marginMode) => marginMode.marketId === variables.marketId
)
);
+70
View File
@@ -1986,8 +1986,14 @@ export type MarginLevels = {
initialLevel: Scalars['String'];
/** Minimal margin for the position to be maintained in the network (unsigned integer) */
maintenanceLevel: Scalars['String'];
/** Margin factor, only relevant for isolated margin mode, else 0 */
marginFactor: Scalars['String'];
/** Margin mode of the party, cross margin or isolated margin */
marginMode: MarginMode;
/** Market in which the margin is required for this party */
market: Market;
/** When in isolated margin, the required order margin level, otherwise, 0 */
orderMarginLevel: Scalars['String'];
/** The party for this margin */
party: Party;
/** If the margin is between maintenance and search, the network will initiate a collateral search, expressed as unsigned integer */
@@ -2010,8 +2016,14 @@ export type MarginLevelsUpdate = {
initialLevel: Scalars['String'];
/** Minimal margin for the position to be maintained in the network (unsigned integer) */
maintenanceLevel: Scalars['String'];
/** Margin factor, only relevant for isolated margin mode, else 0 */
marginFactor: Scalars['String'];
/** Margin mode of the party, cross margin or isolated margin */
marginMode: MarginMode;
/** Market in which the margin is required for this party */
marketId: Scalars['ID'];
/** When in isolated margin, the required order margin level, otherwise, 0 */
orderMarginLevel: Scalars['String'];
/** The party for this margin */
partyId: Scalars['ID'];
/** If the margin is between maintenance and search, the network will initiate a collateral search (unsigned integer) */
@@ -2020,6 +2032,13 @@ export type MarginLevelsUpdate = {
timestamp: Scalars['Timestamp'];
};
export enum MarginMode {
/** Party is in cross margin mode */
MARGIN_MODE_CROSS_MARGIN = 'MARGIN_MODE_CROSS_MARGIN',
/** Party is in isolated margin mode */
MARGIN_MODE_ISOLATED_MARGIN = 'MARGIN_MODE_ISOLATED_MARGIN'
}
/** Represents a product & associated parameters that can be traded on Vega, has an associated OrderBook and Trade history */
export type Market = {
__typename?: 'Market';
@@ -3118,6 +3137,8 @@ export enum OrderRejectionReason {
ORDER_ERROR_INVALID_TIME_IN_FORCE = 'ORDER_ERROR_INVALID_TIME_IN_FORCE',
/** Invalid type */
ORDER_ERROR_INVALID_TYPE = 'ORDER_ERROR_INVALID_TYPE',
/** Party has insufficient funds to cover for the order margin for the new or amended order */
ORDER_ERROR_ISOLATED_MARGIN_CHECK_FAILED = 'ORDER_ERROR_ISOLATED_MARGIN_CHECK_FAILED',
/** Margin check failed - not enough available margin */
ORDER_ERROR_MARGIN_CHECK_FAILED = 'ORDER_ERROR_MARGIN_CHECK_FAILED',
/** Market is closed */
@@ -3138,6 +3159,8 @@ export enum OrderRejectionReason {
ORDER_ERROR_OFFSET_MUST_BE_GREATER_THAN_ZERO = 'ORDER_ERROR_OFFSET_MUST_BE_GREATER_THAN_ZERO',
/** Order is out of sequence */
ORDER_ERROR_OUT_OF_SEQUENCE = 'ORDER_ERROR_OUT_OF_SEQUENCE',
/** Pegged orders are not allowed for a party in isolated margin mode */
ORDER_ERROR_PEGGED_ORDERS_NOT_ALLOWED_IN_ISOLATED_MARGIN_MODE = 'ORDER_ERROR_PEGGED_ORDERS_NOT_ALLOWED_IN_ISOLATED_MARGIN_MODE',
/** A post-only order would produce an aggressive trade and thus it has been rejected */
ORDER_ERROR_POST_ONLY_ORDER_WOULD_TRADE = 'ORDER_ERROR_POST_ONLY_ORDER_WOULD_TRADE',
/** A reduce-ony order would not reduce the party's position and thus it has been rejected */
@@ -3586,6 +3609,41 @@ export type PartyLockedBalance = {
untilEpoch: Scalars['Int'];
};
/** Margin mode selected for the given party and market. */
export type PartyMarginMode = {
__typename?: 'PartyMarginMode';
/** Epoch at which the update happened. */
atEpoch: Scalars['Int'];
/** Selected margin mode. */
marginMode: MarginMode;
/** Margin factor for the market. Isolated mode only. */
margin_factor?: Maybe<Scalars['String']>;
/** Unique ID of the market. */
marketId: Scalars['ID'];
/** Maximum theoretical leverage for the market. Isolated mode only. */
max_theoretical_leverage?: Maybe<Scalars['String']>;
/** Minimum theoretical margin factor for the market. Isolated mode only. */
min_theoretical_margin_factor?: Maybe<Scalars['String']>;
/** Unique ID of the party. */
partyId: Scalars['ID'];
};
/** Edge type containing the deposit and cursor information returned by a PartyMarginModeConnection */
export type PartyMarginModeEdge = {
__typename?: 'PartyMarginModeEdge';
cursor: Scalars['String'];
node: PartyMarginMode;
};
/** Connection type for retrieving cursor-based paginated party margin modes information */
export type PartyMarginModesConnection = {
__typename?: 'PartyMarginModesConnection';
/** The party margin modes */
edges?: Maybe<Array<Maybe<PartyMarginModeEdge>>>;
/** The pagination information */
pageInfo?: Maybe<PageInfo>;
};
/**
* All staking information related to a Party.
* Contains the current recognised balance by the network and
@@ -4438,6 +4496,12 @@ export type Query = {
partiesConnection?: Maybe<PartyConnection>;
/** An entity that is trading on the Vega network */
party?: Maybe<Party>;
/**
* List margin modes per party per market
*
* Get a list of all margin modes, or for a specific market ID, or party ID.
*/
partyMarginModes?: Maybe<PartyMarginModesConnection>;
/** Fetch all positions */
positions?: Maybe<PositionConnection>;
/** A governance proposal located by either its ID or reference. If both are set, ID is used. */
@@ -6211,6 +6275,8 @@ export enum TransferType {
TRANSFER_TYPE_INFRASTRUCTURE_FEE_DISTRIBUTE = 'TRANSFER_TYPE_INFRASTRUCTURE_FEE_DISTRIBUTE',
/** Infrastructure fee paid from general account */
TRANSFER_TYPE_INFRASTRUCTURE_FEE_PAY = 'TRANSFER_TYPE_INFRASTRUCTURE_FEE_PAY',
/** Funds moved from order margin account to margin account. */
TRANSFER_TYPE_ISOLATED_MARGIN_LOW = 'TRANSFER_TYPE_ISOLATED_MARGIN_LOW',
/** Allocates liquidity fee earnings to each liquidity provider's network controlled liquidity fee account. */
TRANSFER_TYPE_LIQUIDITY_FEE_ALLOCATE = 'TRANSFER_TYPE_LIQUIDITY_FEE_ALLOCATE',
/** Liquidity fee received into general account */
@@ -6237,6 +6303,10 @@ export enum TransferType {
TRANSFER_TYPE_MTM_LOSS = 'TRANSFER_TYPE_MTM_LOSS',
/** Funds added to margin account after mark to market gain */
TRANSFER_TYPE_MTM_WIN = 'TRANSFER_TYPE_MTM_WIN',
/** Funds released from order margin account to general. */
TRANSFER_TYPE_ORDER_MARGIN_HIGH = 'TRANSFER_TYPE_ORDER_MARGIN_HIGH',
/** Funds moved from general account to order margin account. */
TRANSFER_TYPE_ORDER_MARGIN_LOW = 'TRANSFER_TYPE_ORDER_MARGIN_LOW',
/** Funds deducted from margin account after a perpetuals funding loss. */
TRANSFER_TYPE_PERPETUALS_FUNDING_LOSS = 'TRANSFER_TYPE_PERPETUALS_FUNDING_LOSS',
/** Funds added to margin account after a perpetuals funding gain. */
@@ -448,7 +448,24 @@ export type CreateReferralSet = {
};
};
export enum MarginMode {
/** Party is in cross margin mode */
MARGIN_MODE_CROSS_MARGIN = 1,
/** Party is in isolated margin mode */
MARGIN_MODE_ISOLATED_MARGIN = 'MARGIN_MODE_ISOLATED_MARGIN',
}
export interface UpdateMarginMode {
market_id: string;
mode: MarginMode;
marginFactor?: string;
}
export interface UpdateMarginModeBody {
updateMarginMode: UpdateMarginMode;
}
export type Transaction =
| UpdateMarginModeBody
| StopOrdersSubmissionBody
| StopOrdersCancellationBody
| OrderSubmissionBody
@@ -465,6 +482,10 @@ export type Transaction =
| ApplyReferralCode
| CreateReferralSet;
export const isMarginModeUpdateTransaction = (
transaction: Transaction
): transaction is UpdateMarginModeBody => 'updateMarginMode' in transaction;
export const isWithdrawTransaction = (
transaction: Transaction
): transaction is WithdrawSubmissionBody => 'withdrawSubmission' in transaction;
@@ -10,6 +10,7 @@ import {
isStopOrdersSubmissionTransaction,
isStopOrdersCancellationTransaction,
determineId,
isMarginModeUpdateTransaction,
} from '@vegaprotocol/wallet';
import { create } from 'zustand';
@@ -58,7 +59,7 @@ export interface VegaTransactionStore {
export const useVegaTransactionStore = create<VegaTransactionStore>()(
subscribeWithSelector((set, get) => ({
transactions: [] as VegaStoredTxState[],
transactions: [] as (VegaStoredTxState | undefined)[],
create: (body: Transaction, order?: OrderTxUpdateFieldsFragment) => {
const transactions = get().transactions;
const now = new Date();
@@ -205,16 +206,23 @@ export const useVegaTransactionStore = create<VegaTransactionStore>()(
isStopOrdersCancellationTransaction(transaction.body);
const isConfirmedStopOrderSubmission =
isStopOrdersSubmissionTransaction(transaction.body);
const isConfirmedMarginModeTransaction =
isMarginModeUpdateTransaction(transaction.body);
if (
(isConfirmedOrderCancellation ||
isConfirmedTransfer ||
isConfirmedStopOrderCancellation ||
isConfirmedStopOrderSubmission) &&
!transactionResult.error &&
transactionResult.status
isConfirmedOrderCancellation ||
isConfirmedTransfer ||
isConfirmedStopOrderCancellation ||
isConfirmedStopOrderSubmission ||
isConfirmedMarginModeTransaction
//transactionResult.status
) {
transaction.status = VegaTxStatus.Complete;
if (transactionResult.error) {
transaction.status = VegaTxStatus.Error;
transaction.error = new Error(transactionResult.error);
} else {
transaction.status = VegaTxStatus.Complete;
}
}
transaction.dialogOpen = true;
transaction.updatedAt = new Date();
@@ -7,6 +7,7 @@ import type {
OrderSubmission,
StopOrdersSubmission,
StopOrderSetup,
UpdateMarginMode,
} from '@vegaprotocol/wallet';
import type {
OrderTxUpdateFieldsFragment,
@@ -26,6 +27,8 @@ import {
isStopOrdersSubmissionTransaction,
isStopOrdersCancellationTransaction,
isReferralRelatedTransaction,
isMarginModeUpdateTransaction,
MarginMode,
} from '@vegaprotocol/wallet';
import { useVegaTransactionStore } from './use-vega-transaction-store';
import { VegaTxStatus } from './types';
@@ -163,6 +166,7 @@ const isClosePositionTransaction = (tx: VegaStoredTxState) => {
};
const isTransactionTypeSupported = (tx: VegaStoredTxState) => {
const marginModeUpdate = isMarginModeUpdateTransaction(tx.body);
const withdraw = isWithdrawTransaction(tx.body);
const submitOrder = isOrderSubmissionTransaction(tx.body);
const cancelOrder = isOrderCancellationTransaction(tx.body);
@@ -173,6 +177,7 @@ const isTransactionTypeSupported = (tx: VegaStoredTxState) => {
const transfer = isTransferTransaction(tx.body);
const referral = isReferralRelatedTransaction(tx.body);
return (
marginModeUpdate ||
withdraw ||
submitOrder ||
cancelOrder ||
@@ -445,6 +450,27 @@ const CancelOrderDetails = ({
);
};
const MarginModeDetails = ({ data }: { data: UpdateMarginMode }) => {
const t = useT();
const { data: markets } = useMarketsMapProvider();
const marketId = data.market_id;
const market = marketId && markets?.[marketId];
if (!market) {
return null;
}
return (
<Panel>
<h4>{t('Update margin mode')}</h4>
<p>{market?.tradableInstrument.instrument.code}</p>
{data.mode === MarginMode.MARGIN_MODE_CROSS_MARGIN
? t('Cross margin mode')
: t('Isolated margin mode {{leverage}}x', {
leverage: 1 / Number(data.marginFactor),
})}
</Panel>
);
};
const CancelStopOrderDetails = ({ stopOrderId }: { stopOrderId: string }) => {
const t = useT();
const formatTrigger = useFormatTrigger();
@@ -598,6 +624,10 @@ export const VegaTransactionDetails = ({ tx }: { tx: VegaStoredTxState }) => {
);
}
if (isMarginModeUpdateTransaction(tx.body)) {
return <MarginModeDetails data={tx.body.updateMarginMode} />;
}
if (isClosePositionTransaction(tx)) {
const transaction = tx.body as BatchMarketInstructionSubmissionBody;
const marketId = first(