From 9c507b145d4a016af8c494c10ac4fb9cc3460b87 Mon Sep 17 00:00:00 2001 From: Bob van der Helm <34470358+bobthebuidlr@users.noreply.github.com> Date: Tue, 13 Feb 2024 16:55:14 +0100 Subject: [PATCH] perps: trading fee + expected price --- src/components/perps/Module/ExpectedPrice.tsx | 28 ++ src/components/perps/Module/Summary.tsx | 29 +- src/components/perps/Module/TradingFee.tsx | 15 +- src/components/perps/Module/usePerpsModule.ts | 8 +- src/configs/chains/neutron/pion-1.ts | 16 +- src/hooks/perps/useTradingFee.ts | 21 -- src/hooks/perps/useTradingFeeAndPrice.ts | 77 +++++ .../generated/mars-perps/MarsPerps.client.ts | 202 +++++++++++--- .../mars-perps/MarsPerps.react-query.ts | 140 +++++++++- .../generated/mars-perps/MarsPerps.types.ts | 264 +++++++++--------- 10 files changed, 582 insertions(+), 218 deletions(-) create mode 100644 src/components/perps/Module/ExpectedPrice.tsx delete mode 100644 src/hooks/perps/useTradingFee.ts create mode 100644 src/hooks/perps/useTradingFeeAndPrice.ts diff --git a/src/components/perps/Module/ExpectedPrice.tsx b/src/components/perps/Module/ExpectedPrice.tsx new file mode 100644 index 00000000..80c23a1a --- /dev/null +++ b/src/components/perps/Module/ExpectedPrice.tsx @@ -0,0 +1,28 @@ +import BigNumber from 'bignumber.js' + +import { CircularProgress } from 'components/common/CircularProgress' +import DisplayCurrency from 'components/common/DisplayCurrency' +import useTradingFeeAndPrice from 'hooks/perps/useTradingFeeAndPrice' +import { BNCoin } from 'types/classes/BNCoin' + +type Props = { + denom: string + newAmount: BigNumber + previousAmount: BigNumber +} + +export const ExpectedPrice = (props: Props) => { + const { data: tradingFeeAndPrice, isLoading } = useTradingFeeAndPrice( + props.denom, + props.newAmount, + props.previousAmount, + ) + + if (isLoading) return + + if (tradingFeeAndPrice?.price) { + return + } + + return '-' +} diff --git a/src/components/perps/Module/Summary.tsx b/src/components/perps/Module/Summary.tsx index 7b4a774e..3a44b908 100644 --- a/src/components/perps/Module/Summary.tsx +++ b/src/components/perps/Module/Summary.tsx @@ -7,10 +7,11 @@ import { ArrowRight } from 'components/common/Icons' import SummaryLine from 'components/common/SummaryLine' import Text from 'components/common/Text' import TradeDirection from 'components/perps/BalancesTable/Columns/TradeDirection' +import { ExpectedPrice } from 'components/perps/Module/ExpectedPrice' import TradingFee from 'components/perps/Module/TradingFee' import { BN_ZERO } from 'constants/math' import useCurrentAccount from 'hooks/accounts/useCurrentAccount' -import useTradingFee from 'hooks/perps/useTradingFee' +import useTradingFeeAndPrice from 'hooks/perps/useTradingFeeAndPrice' import useStore from 'store' import { BNCoin } from 'types/classes/BNCoin' import { formatLeverage } from 'utils/formatters' @@ -20,7 +21,7 @@ type Props = { amount: BigNumber tradeDirection: TradeDirection asset: Asset - previousAmount?: BigNumber | null + previousAmount: BigNumber previousTradeDirection?: 'long' | 'short' previousLeverage?: number | null hasActivePosition: boolean @@ -32,17 +33,21 @@ export default function PerpsSummary(props: Props) { const modifyPerpPosition = useStore((s) => s.modifyPerpPosition) const closePerpPosition = useStore((s) => s.closePerpPosition) const currentAccount = useCurrentAccount() - const { data: tradingFee, isLoading } = useTradingFee(props.asset.denom, props.amount) const newAmount = useMemo( () => (props.previousAmount ?? BN_ZERO).plus(props.amount), [props.amount, props.previousAmount], ) + const { data: tradingFee } = useTradingFeeAndPrice( + props.asset.denom, + newAmount, + props.previousAmount, + ) const onConfirm = useCallback(async () => { if (!currentAccount) return - if (props.previousAmount && newAmount.isZero()) { + if (!props.previousAmount.isZero() && newAmount.isZero()) { await closePerpPosition({ accountId: currentAccount.id, denom: props.asset.denom, @@ -50,7 +55,7 @@ export default function PerpsSummary(props: Props) { return props.onTxExecuted() } - if (props.previousAmount && newAmount) { + if (!props.previousAmount.isZero() && !newAmount.isZero()) { await modifyPerpPosition({ accountId: currentAccount.id, coin: BNCoin.fromDenomAndBigNumber(props.asset.denom, newAmount), @@ -75,12 +80,22 @@ export default function PerpsSummary(props: Props) { Summary - - + + + - + - diff --git a/src/components/perps/Module/TradingFee.tsx b/src/components/perps/Module/TradingFee.tsx index 5544ea1c..617d63d1 100644 --- a/src/components/perps/Module/TradingFee.tsx +++ b/src/components/perps/Module/TradingFee.tsx @@ -2,18 +2,23 @@ import BigNumber from 'bignumber.js' import { CircularProgress } from 'components/common/CircularProgress' import DisplayCurrency from 'components/common/DisplayCurrency' -import useTradingFee from 'hooks/perps/useTradingFee' +import useTradingFeeAndPrice from 'hooks/perps/useTradingFeeAndPrice' type Props = { denom: string - amount: BigNumber + newAmount: BigNumber + previousAmount: BigNumber } export default function TradingFee(props: Props) { - const { data: openingFee, isLoading } = useTradingFee(props.denom, props.amount) + const { data: tradingFeeAndPrice, isLoading } = useTradingFeeAndPrice( + props.denom, + props.newAmount, + props.previousAmount, + ) if (isLoading) return - if (props.amount.isZero() || !openingFee) return '-' + if (props.newAmount.isEqualTo(props.previousAmount) || !tradingFeeAndPrice?.fee) return '-' - return + return } diff --git a/src/components/perps/Module/usePerpsModule.ts b/src/components/perps/Module/usePerpsModule.ts index 20dc32c8..e6813eb6 100644 --- a/src/components/perps/Module/usePerpsModule.ts +++ b/src/components/perps/Module/usePerpsModule.ts @@ -38,7 +38,11 @@ export default function usePerpsModule(amount: BigNumber | null) { const previousLeverage = useMemo( () => previousAmount - ? price.times(demagnify(previousAmount, perpsAsset)).div(accountNetValue).plus(1).toNumber() + ? price + .times(demagnify(previousAmount.abs(), perpsAsset)) + .div(accountNetValue) + .plus(1) + .toNumber() : null, [accountNetValue, perpsAsset, previousAmount, price], ) @@ -46,7 +50,7 @@ export default function usePerpsModule(amount: BigNumber | null) { const leverage = useMemo( () => price - .times(demagnify(previousAmount.plus(amount ?? BN_ZERO), perpsAsset)) + .times(demagnify(previousAmount.plus(amount ?? BN_ZERO).abs(), perpsAsset)) .div(accountNetValue) .plus(1) .toNumber(), diff --git a/src/configs/chains/neutron/pion-1.ts b/src/configs/chains/neutron/pion-1.ts index 2cfd289d..a3c125ba 100644 --- a/src/configs/chains/neutron/pion-1.ts +++ b/src/configs/chains/neutron/pion-1.ts @@ -21,14 +21,14 @@ const Pion1: ChainConfig = { id: ChainInfoID.Pion1, name: 'Neutron Testnet', contracts: { - redBank: 'neutron1gpv59ff87mfvx8s3fn5ku3l8dn94fkj4q37sruhwfl0zzgjsejqs3xejyj', - incentives: 'neutron1au78lscqqh77ghvl6eq2d58vy439q0gprhz0sc5q4r9svh63hquqtwlrsw', - oracle: 'neutron1z44naqtpn20z5yws7updsgcplm7tcfkcn67uejvc0l7n8hy6vupq0894qs', - swapper: 'neutron1td4dn53k7ythdj8ah3xv5p66swq3sy2a9jzq4yrue8aa4dvwacrs7dachf', - params: 'neutron16l9j74q6ht9ycd37qxt6tz83l3r3cwec4qu9r5mkd66kcve23ywspjqhjp', - creditManager: 'neutron1swud86k6acvpjfn68cv6tz3h7z72nz395d7y5e3yxknrc8yl9faqxn5jjw', - accountNft: 'neutron1apus79ka5v30wmwdxzzapprrzxxw6mz0hc0uk3g030t0m5f0asuq8x3ldf', - perps: 'neutron1ssnc38h40fu0d2et8f38z83ealgugh06r4anqa6dn6hlz6syqaqsmj6zcy', + redBank: 'neutron1h7lvw8nm64x3zxlue6ec3vrk4e504d7c2wqq6y9uq2nu2shygh8qxm22up', + incentives: 'neutron1e28g4d93rthgjrtrxsze2f5lcljsxst24szhx0gjsvcmwzqsdruswau7hv', + oracle: 'neutron1lwwmygj9cfm5jy623vvk37athq5fnjnm00wfjap2q49lfk8wylkqtujcym', + swapper: 'neutron1yk90r8efz897ev7vve9anfl4w342czn8f35qlyd3s2hsg4tctdms7vwexp', + params: 'neutron16kqg3hr2qc36gz2wqvdzsctatkmzd3ss5gc07tnj6u3n5ajw89asrx8hfp', + creditManager: 'neutron1kj50g96c86nu7jmy5y7uy5cyjanntgru0eekmwz2qcmyyvx6383s8dgvm6', + accountNft: 'neutron17wvpxdc3k37054ume0ga4r0r6ra2rpfe622m0ecgd9s7xd5s0qusspc4ct', + perps: 'neutron14v9g7regs90qvful7djcajsvrfep5pg9qau7qm6wya6c2lzcpnms692dlt', pyth: 'neutron15ldst8t80982akgr8w8ekcytejzkmfpgdkeq4xgtge48qs7435jqp87u3t', }, endpoints: { diff --git a/src/hooks/perps/useTradingFee.ts b/src/hooks/perps/useTradingFee.ts deleted file mode 100644 index ddc74453..00000000 --- a/src/hooks/perps/useTradingFee.ts +++ /dev/null @@ -1,21 +0,0 @@ -import BigNumber from 'bignumber.js' -import useSWR from 'swr' - -import useChainConfig from 'hooks/useChainConfig' -import useClients from 'hooks/useClients' -import useDebounce from 'hooks/useDebounce' -import { BNCoin } from 'types/classes/BNCoin' -import { BN } from 'utils/helpers' - -export default function useTradingFee(denom: string, amount: BigNumber) { - const chainConfig = useChainConfig() - const debouncedAmount = useDebounce(amount.toString(), 500) - const clients = useClients() - const enabled = !amount.isZero() && clients - - return useSWR(enabled && `${chainConfig.id}/perps/${denom}/tradingFee/${debouncedAmount}`, () => - clients!.perps - .openingFee({ denom, size: amount as any }) - .then((resp) => ({ rate: BN(resp.rate), fee: BNCoin.fromCoin(resp.fee) })), - ) -} diff --git a/src/hooks/perps/useTradingFeeAndPrice.ts b/src/hooks/perps/useTradingFeeAndPrice.ts new file mode 100644 index 00000000..9a4b576e --- /dev/null +++ b/src/hooks/perps/useTradingFeeAndPrice.ts @@ -0,0 +1,77 @@ +import BigNumber from 'bignumber.js' +import useSWR from 'swr' + +import { BN_ZERO } from 'constants/math' +import useCurrentAccount from 'hooks/accounts/useCurrentAccount' +import useChainConfig from 'hooks/useChainConfig' +import useClients from 'hooks/useClients' +import useDebounce from 'hooks/useDebounce' +import { BNCoin } from 'types/classes/BNCoin' +import { BN } from 'utils/helpers' + +export default function useTradingFeeAndPrice( + denom: string, + newAmount: BigNumber, + previousAmount: BigNumber, +) { + const chainConfig = useChainConfig() + const accountId = useCurrentAccount()?.id + const debouncedAmount = useDebounce(newAmount, 500) + const clients = useClients() + const enabled = !debouncedAmount.isEqualTo(previousAmount) && clients && !!accountId + + return useSWR( + enabled && `${chainConfig.id}/perps/${denom}/positionFeeAndPrice/${debouncedAmount}`, + async () => { + const isChangingTradeDirection = + newAmount.isNegative() !== previousAmount.isNegative() && !previousAmount.isZero() + + if (!isChangingTradeDirection) { + const positionFees = await clients!.perps.positionFees({ + denom, + newSize: newAmount.toString() as any, + accountId: accountId!, + }) + + return { + price: positionFees.opening_exec_price + ? BN(positionFees.opening_exec_price) + : BN(positionFees.closing_exec_price ?? BN_ZERO), + fee: BNCoin.fromDenomAndBigNumber( + positionFees.base_denom, + BN(positionFees.opening_fee).plus(positionFees.closing_fee), + ), + rate: BN(0.005), + } + } + + // WHen direction is changed, we need to query both the 'closing' fees + // and also query how the new position would be opened. SC limits flipping trade direction. + const closingPositionFees$ = clients!.perps.positionFees({ + denom, + newSize: '0' as any, + accountId: accountId!, + }) + + const openingPositionFees$ = clients!.perps.positionFees({ + denom, + newSize: newAmount.toString() as any, + accountId: '91283123987467', // TODO: Remove this hard-coded value. SC currently does not allow flipping, so providing arbitrary accountId prevents this + }) + + return await Promise.all([closingPositionFees$, openingPositionFees$]).then( + ([closingPositionFees, openingPositionFees]) => ({ + price: BN(openingPositionFees.opening_exec_price ?? 0), + fee: BNCoin.fromDenomAndBigNumber( + closingPositionFees.base_denom, + BN(closingPositionFees.opening_fee) + .plus(closingPositionFees.closing_fee) + .plus(openingPositionFees.opening_fee) + .plus(openingPositionFees.closing_fee), + ), + rate: BN(0.005), + }), + ) + }, + ) +} diff --git a/src/types/generated/mars-perps/MarsPerps.client.ts b/src/types/generated/mars-perps/MarsPerps.client.ts index e3e32221..17a895cc 100644 --- a/src/types/generated/mars-perps/MarsPerps.client.ts +++ b/src/types/generated/mars-perps/MarsPerps.client.ts @@ -5,41 +5,32 @@ * and run the @cosmwasm/ts-codegen generate command to regenerate this file. */ -import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from '@cosmjs/cosmwasm-stargate' -import { StdFee } from '@cosmjs/amino' +import { StdFee } from "@cosmjs/amino"; +import { CosmWasmClient, ExecuteResult, SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate"; import { - Decimal, - Uint128, - OracleBaseForString, - ParamsBaseForString, - InstantiateMsg, - ExecuteMsg, - OwnerUpdate, - SignedDecimal, - QueryMsg, - ConfigForString, - DenomStateResponse, - Funding, + Accounting, ArrayOfDenomStateResponse, - DepositResponse, ArrayOfDepositResponse, - TradingFee, - Coin, - OwnerResponse, - PerpDenomState, - DenomPnlValues, - PnL, - PositionResponse, - PerpPosition, - PositionPnl, - PnlCoins, - PnlValues, ArrayOfPositionResponse, - PositionsByAccountResponse, ArrayOfUnlockState, - UnlockState, - VaultState, -} from './MarsPerps.types' + Coin, + ConfigForString, + Decimal, + DenomStateResponse, + DepositResponse, + OwnerResponse, + OwnerUpdate, + PerpDenomState, + PnlAmounts, + PositionFeesResponse, + PositionResponse, + PositionsByAccountResponse, + SignedDecimal, + TradingFee, + Uint128, + VaultState +} from "./MarsPerps.types"; + export interface MarsPerpsReadOnlyInterface { contractAddress: string owner: () => Promise @@ -63,13 +54,7 @@ export interface MarsPerpsReadOnlyInterface { startAfter?: string }) => Promise unlocks: ({ depositor }: { depositor: string }) => Promise - position: ({ - accountId, - denom, - }: { - accountId: string - denom: string - }) => Promise + denomAccounting: ({ denom }: { denom: string }) => Promise positions: ({ limit, startAfter, @@ -80,6 +65,32 @@ export interface MarsPerpsReadOnlyInterface { positionsByAccount: ({ accountId }: { accountId: string }) => Promise totalPnl: () => Promise openingFee: ({ denom, size }: { denom: string; size: SignedDecimal }) => Promise + denomRealizedPnlForAccount: ({ + accountId, + denom, + }: { + accountId: string + denom: string + }) => Promise + position: ({ + accountId, + denom, + newSize, + }: { + accountId: string + denom: string + newSize?: SignedDecimal + }) => Promise + positionFees: ({ + accountId, + denom, + newSize, + }: { + accountId: string + denom: string + newSize: SignedDecimal + }) => Promise + totalAccounting: () => Promise } export class MarsPerpsQueryClient implements MarsPerpsReadOnlyInterface { client: CosmWasmClient @@ -102,6 +113,10 @@ export class MarsPerpsQueryClient implements MarsPerpsReadOnlyInterface { this.positionsByAccount = this.positionsByAccount.bind(this) this.totalPnl = this.totalPnl.bind(this) this.openingFee = this.openingFee.bind(this) + this.denomAccounting = this.denomAccounting.bind(this) + this.totalAccounting = this.totalAccounting.bind(this) + this.denomRealizedPnlForAccount = this.denomRealizedPnlForAccount.bind(this) + this.positionFees = this.positionFees.bind(this) } owner = async (): Promise => { @@ -175,16 +190,10 @@ export class MarsPerpsQueryClient implements MarsPerpsReadOnlyInterface { }, }) } - position = async ({ - accountId, - denom, - }: { - accountId: string - denom: string - }): Promise => { + + denomAccounting = async ({ denom }: { denom: string }): Promise => { return this.client.queryContractSmart(this.contractAddress, { - position: { - account_id: accountId, + denom_accounting: { denom, }, }) @@ -233,6 +242,63 @@ export class MarsPerpsQueryClient implements MarsPerpsReadOnlyInterface { }, }) } + + denomRealizedPnlForAccount = async ({ + accountId, + denom, + }: { + accountId: string + denom: string + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + denom_realized_pnl_for_account: { + account_id: accountId, + denom, + }, + }) + } + + position = async ({ + accountId, + denom, + newSize, + }: { + accountId: string + denom: string + newSize?: SignedDecimal + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + position: { + account_id: accountId, + denom, + new_size: newSize, + }, + }) + } + + positionFees = async ({ + accountId, + denom, + newSize, + }: { + accountId: string + denom: string + newSize: SignedDecimal + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + position_fees: { + account_id: accountId, + denom, + new_size: newSize, + }, + }) + } + + totalAccounting = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + total_accounting: {}, + }) + } } export interface MarsPerpsInterface extends MarsPerpsReadOnlyInterface { contractAddress: string @@ -323,6 +389,20 @@ export interface MarsPerpsInterface extends MarsPerpsReadOnlyInterface { memo?: string, _funds?: Coin[], ) => Promise + modifyPosition: ( + { + accountId, + denom, + newSize, + }: { + accountId: string + denom: string + newSize: SignedDecimal + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[], + ) => Promise } export class MarsPerpsClient extends MarsPerpsQueryClient implements MarsPerpsInterface { client: SigningCosmWasmClient @@ -343,6 +423,7 @@ export class MarsPerpsClient extends MarsPerpsQueryClient implements MarsPerpsIn this.withdraw = this.withdraw.bind(this) this.openPosition = this.openPosition.bind(this) this.closePosition = this.closePosition.bind(this) + this.modifyPosition = this.modifyPosition.bind(this) } updateOwner = async ( @@ -547,4 +628,33 @@ export class MarsPerpsClient extends MarsPerpsQueryClient implements MarsPerpsIn _funds, ) } + modifyPosition = async ( + { + accountId, + denom, + newSize, + }: { + accountId: string + denom: string + newSize: SignedDecimal + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[], + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + modify_position: { + account_id: accountId, + denom, + new_size: newSize, + }, + }, + fee, + memo, + _funds, + ) + } } diff --git a/src/types/generated/mars-perps/MarsPerps.react-query.ts b/src/types/generated/mars-perps/MarsPerps.react-query.ts index d7e7c2a0..55a0f36a 100644 --- a/src/types/generated/mars-perps/MarsPerps.react-query.ts +++ b/src/types/generated/mars-perps/MarsPerps.react-query.ts @@ -19,6 +19,10 @@ import { SignedDecimal, QueryMsg, ConfigForString, + Accounting, + Balance, + CashFlow, + PnlAmounts, DenomStateResponse, Funding, ArrayOfDenomStateResponse, @@ -28,13 +32,13 @@ import { Coin, OwnerResponse, PerpDenomState, - DenomPnlValues, + PnlValues, PnL, PositionResponse, PerpPosition, PositionPnl, PnlCoins, - PnlValues, + PositionFeesResponse, ArrayOfPositionResponse, PositionsByAccountResponse, ArrayOfUnlockState, @@ -82,6 +86,27 @@ export const marsPerpsQueryKeys = { [{ ...marsPerpsQueryKeys.address(contractAddress)[0], method: 'total_pnl', args }] as const, openingFee: (contractAddress: string | undefined, args?: Record) => [{ ...marsPerpsQueryKeys.address(contractAddress)[0], method: 'opening_fee', args }] as const, + denomAccounting: (contractAddress: string | undefined, args?: Record) => + [ + { ...marsPerpsQueryKeys.address(contractAddress)[0], method: 'denom_accounting', args }, + ] as const, + totalAccounting: (contractAddress: string | undefined, args?: Record) => + [ + { ...marsPerpsQueryKeys.address(contractAddress)[0], method: 'total_accounting', args }, + ] as const, + denomRealizedPnlForAccount: ( + contractAddress: string | undefined, + args?: Record, + ) => + [ + { + ...marsPerpsQueryKeys.address(contractAddress)[0], + method: 'denom_realized_pnl_for_account', + args, + }, + ] as const, + positionFees: (contractAddress: string | undefined, args?: Record) => + [{ ...marsPerpsQueryKeys.address(contractAddress)[0], method: 'position_fees', args }] as const, } export interface MarsPerpsReactQuery { client: MarsPerpsQueryClient | undefined @@ -92,6 +117,90 @@ export interface MarsPerpsReactQuery { initialData?: undefined } } +export interface MarsPerpsPositionFeesQuery + extends MarsPerpsReactQuery { + args: { + accountId: string + denom: string + newSize: SignedDecimal + } +} +export function useMarsPerpsPositionFeesQuery({ + client, + args, + options, +}: MarsPerpsPositionFeesQuery) { + return useQuery( + marsPerpsQueryKeys.positionFees(client?.contractAddress, args), + () => + client + ? client.positionFees({ + accountId: args.accountId, + denom: args.denom, + newSize: args.newSize, + }) + : Promise.reject(new Error('Invalid client')), + { ...options, enabled: !!client && (options?.enabled != undefined ? options.enabled : true) }, + ) +} +export interface MarsPerpsDenomRealizedPnlForAccountQuery + extends MarsPerpsReactQuery { + args: { + accountId: string + denom: string + } +} +export function useMarsPerpsDenomRealizedPnlForAccountQuery({ + client, + args, + options, +}: MarsPerpsDenomRealizedPnlForAccountQuery) { + return useQuery( + marsPerpsQueryKeys.denomRealizedPnlForAccount(client?.contractAddress, args), + () => + client + ? client.denomRealizedPnlForAccount({ + accountId: args.accountId, + denom: args.denom, + }) + : Promise.reject(new Error('Invalid client')), + { ...options, enabled: !!client && (options?.enabled != undefined ? options.enabled : true) }, + ) +} +export interface MarsPerpsTotalAccountingQuery + extends MarsPerpsReactQuery {} +export function useMarsPerpsTotalAccountingQuery({ + client, + options, +}: MarsPerpsTotalAccountingQuery) { + return useQuery( + marsPerpsQueryKeys.totalAccounting(client?.contractAddress), + () => (client ? client.totalAccounting() : Promise.reject(new Error('Invalid client'))), + { ...options, enabled: !!client && (options?.enabled != undefined ? options.enabled : true) }, + ) +} +export interface MarsPerpsDenomAccountingQuery + extends MarsPerpsReactQuery { + args: { + denom: string + } +} +export function useMarsPerpsDenomAccountingQuery({ + client, + args, + options, +}: MarsPerpsDenomAccountingQuery) { + return useQuery( + marsPerpsQueryKeys.denomAccounting(client?.contractAddress, args), + () => + client + ? client.denomAccounting({ + denom: args.denom, + }) + : Promise.reject(new Error('Invalid client')), + { ...options, enabled: !!client && (options?.enabled != undefined ? options.enabled : true) }, + ) +} export interface MarsPerpsOpeningFeeQuery extends MarsPerpsReactQuery { args: { denom: string @@ -177,6 +286,7 @@ export interface MarsPerpsPositionQuery args: { accountId: string denom: string + newSize?: SignedDecimal } } export function useMarsPerpsPositionQuery({ @@ -191,6 +301,7 @@ export function useMarsPerpsPositionQuery({ ? client.position({ accountId: args.accountId, denom: args.denom, + newSize: args.newSize, }) : Promise.reject(new Error('Invalid client')), { ...options, enabled: !!client && (options?.enabled != undefined ? options.enabled : true) }, @@ -364,6 +475,31 @@ export function useMarsPerpsOwnerQuery({ { ...options, enabled: !!client && (options?.enabled != undefined ? options.enabled : true) }, ) } +export interface MarsPerpsModifyPositionMutation { + client: MarsPerpsClient + msg: { + accountId: string + denom: string + newSize: SignedDecimal + } + args?: { + fee?: number | StdFee | 'auto' + memo?: string + funds?: Coin[] + } +} +export function useMarsPerpsModifyPositionMutation( + options?: Omit< + UseMutationOptions, + 'mutationFn' + >, +) { + return useMutation( + ({ client, msg, args: { fee, memo, funds } = {} }) => + client.modifyPosition(msg, fee, memo, funds), + options, + ) +} export interface MarsPerpsClosePositionMutation { client: MarsPerpsClient msg: { diff --git a/src/types/generated/mars-perps/MarsPerps.types.ts b/src/types/generated/mars-perps/MarsPerps.types.ts index ea93234d..aacba981 100644 --- a/src/types/generated/mars-perps/MarsPerps.types.ts +++ b/src/types/generated/mars-perps/MarsPerps.types.ts @@ -22,70 +22,70 @@ export interface InstantiateMsg { } export type ExecuteMsg = | { - update_owner: OwnerUpdate -} + update_owner: OwnerUpdate + } | { - init_denom: { - denom: string - max_funding_velocity: Decimal - skew_scale: Decimal - } -} + init_denom: { + denom: string + max_funding_velocity: Decimal + skew_scale: Decimal + } + } | { - enable_denom: { - denom: string - } -} + enable_denom: { + denom: string + } + } | { - disable_denom: { - denom: string - } -} + disable_denom: { + denom: string + } + } | { - deposit: {} -} + deposit: {} + } | { - unlock: { - shares: Uint128 - } -} + unlock: { + shares: Uint128 + } + } | { - withdraw: {} -} + withdraw: {} + } | { - open_position: { - account_id: string - denom: string - size: SignedDecimal - } -} + open_position: { + account_id: string + denom: string + size: SignedDecimal + } + } | { - close_position: { - account_id: string - denom: string - } -} + close_position: { + account_id: string + denom: string + } + } | { - modify_position: { - account_id: string - denom: string - new_size: SignedDecimal - } -} + modify_position: { + account_id: string + denom: string + new_size: SignedDecimal + } + } export type OwnerUpdate = | { - propose_new_owner: { - proposed: string - } -} + propose_new_owner: { + proposed: string + } + } | 'clear_proposed' | 'accept_proposed' | 'abolish_owner_role' | { - set_emergency_owner: { - emergency_owner: string - } -} + set_emergency_owner: { + emergency_owner: string + } + } | 'clear_emergency_owner' export interface SignedDecimal { abs: Decimal @@ -94,86 +94,94 @@ export interface SignedDecimal { } export type QueryMsg = | { - owner: {} -} + owner: {} + } | { - config: {} -} + config: {} + } | { - vault_state: {} -} + vault_state: {} + } | { - denom_state: { - denom: string - } -} + denom_state: { + denom: string + } + } | { - perp_denom_state: { - denom: string - } -} + perp_denom_state: { + denom: string + } + } | { - denom_states: { - limit?: number | null - start_after?: string | null - } -} + denom_states: { + limit?: number | null + start_after?: string | null + } + } | { - deposit: { - depositor: string - } -} + deposit: { + depositor: string + } + } | { - deposits: { - limit?: number | null - start_after?: string | null - } -} + deposits: { + limit?: number | null + start_after?: string | null + } + } | { - unlocks: { - depositor: string - } -} + unlocks: { + depositor: string + } + } | { - position: { - account_id: string - denom: string - } -} + position: { + account_id: string + denom: string + new_size?: SignedDecimal | null + } + } | { - positions: { - limit?: number | null - start_after?: [string, string] | null - } -} + positions: { + limit?: number | null + start_after?: [string, string] | null + } + } | { - positions_by_account: { - account_id: string - } -} + positions_by_account: { + account_id: string + } + } | { - total_pnl: {} -} + total_pnl: {} + } | { - opening_fee: { - denom: string - size: SignedDecimal - } -} + opening_fee: { + denom: string + size: SignedDecimal + } + } | { - denom_accounting: { - denom: string - } -} + denom_accounting: { + denom: string + } + } | { - total_accounting: {} -} + total_accounting: {} + } | { - denom_realized_pnl_for_account: { - account_id: string - denom: string - } -} + denom_realized_pnl_for_account: { + account_id: string + denom: string + } + } + | { + position_fees: { + account_id: string + denom: string + new_size: SignedDecimal + } + } export interface ConfigForString { base_denom: string closing_fee_rate: Decimal @@ -203,7 +211,7 @@ export interface CashFlow { opening_fee: SignedDecimal price_pnl: SignedDecimal } -export interface RealizedPnlAmounts { +export interface PnlAmounts { accrued_funding: SignedDecimal closing_fee: SignedDecimal opening_fee: SignedDecimal @@ -250,26 +258,26 @@ export interface PerpDenomState { denom: string enabled: boolean long_oi: Decimal - pnl_values: DenomPnlValues + pnl_values: PnlValues rate: SignedDecimal short_oi: Decimal total_entry_cost: SignedDecimal total_entry_funding: SignedDecimal } -export interface DenomPnlValues { +export interface PnlValues { accrued_funding: SignedDecimal - closing_fees: SignedDecimal + closing_fee: SignedDecimal pnl: SignedDecimal price_pnl: SignedDecimal } export type PnL = | 'break_even' | { - profit: Coin -} + profit: Coin + } | { - loss: Coin -} + loss: Coin + } export interface PositionResponse { account_id: string position: PerpPosition @@ -282,11 +290,12 @@ export interface PerpPosition { denom: string entry_exec_price: Decimal entry_price: Decimal - realised_pnl: RealizedPnlAmounts + realised_pnl: PnlAmounts size: SignedDecimal unrealised_pnl: PositionPnl } export interface PositionPnl { + amounts: PnlAmounts coins: PnlCoins values: PnlValues } @@ -294,11 +303,12 @@ export interface PnlCoins { closing_fee: Coin pnl: PnL } -export interface PnlValues { - accrued_funding: SignedDecimal - closing_fee: SignedDecimal - pnl: SignedDecimal - price_pnl: SignedDecimal +export interface PositionFeesResponse { + base_denom: string + closing_exec_price?: Decimal | null + closing_fee: Uint128 + opening_exec_price?: Decimal | null + opening_fee: Uint128 } export type ArrayOfPositionResponse = PositionResponse[] export interface PositionsByAccountResponse {