+
{items.map((item, index) => (
{item}
- {index !== items.length - 1 && }
+ {index !== items.length - 1 && (
+
+ )}
))}
diff --git a/src/components/portfolio/Account/Strategies.tsx b/src/components/portfolio/Account/Strategies.tsx
index 0c5611e67..f804ecc43 100644
--- a/src/components/portfolio/Account/Strategies.tsx
+++ b/src/components/portfolio/Account/Strategies.tsx
@@ -12,7 +12,7 @@ interface Props {
function Content(props: Props) {
const { account } = props
- if (account.vaults.length === 0 && account.stakedAstroLps.length === 0) {
+ if (account.vaults.length === 0 && account.stakedAstroLps.length === 0 && !account.perpsVault) {
return null
}
diff --git a/src/components/portfolio/Overview/Summary.tsx b/src/components/portfolio/Overview/Summary.tsx
index f12bc3f85..13e94a1b2 100644
--- a/src/components/portfolio/Overview/Summary.tsx
+++ b/src/components/portfolio/Overview/Summary.tsx
@@ -16,7 +16,7 @@ import useVaultAprs from 'hooks/vaults/useVaultAprs'
import useStore from 'store'
import { getAccountSummaryStats } from 'utils/accounts'
import { DEFAULT_PORTFOLIO_STATS } from 'utils/constants'
-import { mergeBNCoinArrays } from 'utils/helpers'
+import { mergeBNCoinArrays, mergePerpsVaults } from 'utils/helpers'
export default function PortfolioSummary() {
const { address: urlAddress } = useParams()
@@ -48,6 +48,7 @@ export default function PortfolioSummary() {
combinedAccount.stakedAstroLps,
account.stakedAstroLps,
)
+
return combinedAccount
},
{
@@ -62,6 +63,8 @@ export default function PortfolioSummary() {
kind: 'default' as AccountKind,
} as Account,
)
+ const combinedPerpsVaults = mergePerpsVaults(allAccounts.map((account) => account.perpsVault))
+ combinedAccount.perpsVault = combinedPerpsVaults.denom !== '' ? combinedPerpsVaults : null
const { positionValue, debts, netWorth, collateralValue, apy, leverage } =
getAccountSummaryStats(
diff --git a/src/components/trade/TradeChart/constants.ts b/src/components/trade/TradeChart/constants.ts
index 2cab4f55a..a60c728ac 100644
--- a/src/components/trade/TradeChart/constants.ts
+++ b/src/components/trade/TradeChart/constants.ts
@@ -16,16 +16,17 @@ export const disabledFeatures: ChartingLibraryFeatureset[] = [
'symbol_info',
'go_to_date',
'timeframes_toolbar',
+ 'create_volume_indicator_by_default',
]
export const enabledFeatures: ChartingLibraryFeatureset[] = [
'timezone_menu',
'header_settings',
- 'use_localstorage_for_settings',
'chart_zoom',
'horz_touch_drag_scroll',
'vert_touch_drag_scroll',
'control_bar',
+ 'use_localstorage_for_settings',
]
export const disabledFeaturesMobile: ChartingLibraryFeatureset[] = [
@@ -47,11 +48,12 @@ export const disabledFeaturesMobile: ChartingLibraryFeatureset[] = [
'symbol_info',
'go_to_date',
'timeframes_toolbar',
+ 'create_volume_indicator_by_default',
]
export const enabledFeaturesMobile: ChartingLibraryFeatureset[] = [
'horz_touch_drag_scroll',
- 'use_localstorage_for_settings',
'chart_zoom',
'hide_left_toolbar_by_default',
+ 'use_localstorage_for_settings',
]
diff --git a/src/components/trade/TradeChart/index.tsx b/src/components/trade/TradeChart/index.tsx
index afa874ee7..77a31dcba 100644
--- a/src/components/trade/TradeChart/index.tsx
+++ b/src/components/trade/TradeChart/index.tsx
@@ -32,6 +32,7 @@ import {
} from 'utils/charting_library'
import { formatValue, getPerpsPriceDecimals, magnify } from 'utils/formatters'
import { getTradingViewSettings } from 'utils/theme'
+import { BN } from 'utils/helpers'
interface Props {
buyAsset: Asset
@@ -41,7 +42,8 @@ interface Props {
perpsPosition?: PerpsPosition
liquidationPrice?: number
limitOrders?: PerpPositionRow[]
- onCreateLimitOrder?: (price: number) => void
+ onCreateLimitOrder?: (price: BigNumber) => void
+ onCreateStopOrder?: (price: BigNumber) => void
}
let chartWidget: IChartingLibraryWidget
@@ -52,8 +54,8 @@ function getLimitOrderText(
currentPosition: 'long' | 'short' | null,
positionAmount: BigNumber | null,
) {
- let label = 'Limit'
-
+ let label = order.type === 'stop' ? 'Stop' : 'Limit'
+ console.log(order)
if (positionAmount && order.amount.abs().isEqualTo(positionAmount.abs())) {
const isClosing =
(currentPosition === 'long' && order.tradeDirection === 'short') ||
@@ -78,6 +80,7 @@ function isAutomaticAddedLine(shapeName: string, shape: any) {
return (
shape.text.includes('Limit') ||
+ shape.text.includes('Stop') ||
shape.text.includes('Entry') ||
shape.text.includes('Liquidation') ||
shape.text.includes('Close')
@@ -105,7 +108,7 @@ export default function TradeChart(props: Props) {
)
const chartName = useMemo(() => getChartName(props), [props])
- const { onCreateLimitOrder, isPerps } = props
+ const { onCreateLimitOrder, onCreateStopOrder, isPerps } = props
const [ratio, priceBuyAsset, priceSellAsset] = useMemo(() => {
const priceBuyAsset = props.buyAsset?.price?.amount
@@ -133,9 +136,9 @@ export default function TradeChart(props: Props) {
const chart = chartWidget.activeChart()
if (!chart) return
const chartStore = JSON.parse(localStorage.getItem(LocalStorageKeys.TV_CHART_STORE) ?? '{}')
- const currentChartStore = chartStore[chartName]
- if (!currentChartStore) return
- currentChartStore.forEach((shape: TradingViewShape) => {
+ const currentChartShapeStore = chartStore[chartName]
+ if (!currentChartShapeStore) return
+ currentChartShapeStore.forEach((shape: TradingViewShape) => {
if (Array.isArray(shape.points)) {
if (shape.points.length === 0) return
chart.createMultipointShape(shape.points, shape.shape)
@@ -143,14 +146,26 @@ export default function TradeChart(props: Props) {
chart.createShape(shape.points, shape.shape)
}
})
- if (!isPerps || !onCreateLimitOrder) return
+ const currentChartStudyStore = chartStore[`${chartName}-studies`]
+ if (!currentChartStudyStore) return
+ currentChartStudyStore.forEach((studyName: string) => {
+ chart.createStudy(studyName)
+ })
+ if (!isPerps || !onCreateLimitOrder || !onCreateStopOrder) return
chartWidget.onContextMenu((unixTime, price) => {
return [
{
position: 'top',
text: 'Set Limit Order Price',
click: () => {
- onCreateLimitOrder(price)
+ onCreateLimitOrder?.(BN(price))
+ },
+ },
+ {
+ position: 'top',
+ text: 'Set Stop Order Price',
+ click: () => {
+ onCreateStopOrder?.(BN(price))
},
},
]
@@ -159,101 +174,114 @@ export default function TradeChart(props: Props) {
console.info('Error on loading chart', e)
return
}
- }, [chartName, onCreateLimitOrder, isPerps])
-
- const updateShapes = useCallback(() => {
- const chart = chartWidget.activeChart()
- const settings = getTradingViewSettings(theme)
- const oraclePriceDecimalDiff = props.buyAsset.decimals - PRICE_ORACLE_DECIMALS
- const { downColor, upColor } = settings.chartStyle
- const currentShapes = [] as TradingViewShape[]
- const allShapes = chart.getAllShapes()
- allShapes.forEach((shape) => {
- const currentShape = chart.getShapeById(shape.id).getProperties()
- const currentShapePoints = chart.getShapeById(shape.id).getPoints()
- if (isAutomaticAddedLine(shape.name, currentShape)) {
- chart.removeEntity(shape.id)
- } else {
- currentShapes.push({
- points: currentShapePoints,
- shape: { ...currentShape, shape: shape.name as TradingViewShapeNames },
- })
- }
- })
+ }, [chartName, onCreateLimitOrder, onCreateStopOrder, isPerps])
- const newTvChartStore = JSON.stringify({
- ...JSON.parse(tvChartStore),
- [chartName]: currentShapes,
- })
- setTvChartStore(newTvChartStore)
-
- if (entryPrice) {
- chart.createShape(
- { price: entryPrice, time: moment().unix() },
- {
- shape: 'horizontal_line',
- lock: true,
- disableSelection: true,
- zOrder: 'top',
- text: 'Entry',
- overrides: {
- linecolor: tradeDirection === 'long' ? upColor : downColor,
- textcolor: tradeDirection === 'long' ? upColor : downColor,
- linestyle: 0,
- linewidth: 1,
- showLabel: true,
- },
- },
- )
- }
+ const updateShapesAndStudies = useCallback(() => {
+ try {
+ const chart = chartWidget.activeChart()
+ const settings = getTradingViewSettings(theme)
+ const oraclePriceDecimalDiff = props.buyAsset.decimals - PRICE_ORACLE_DECIMALS
+ const { downColor, upColor } = settings.chartStyle
+ const currentShapes = [] as TradingViewShape[]
+ const currentStudies = [] as string[]
+ const allShapes = chart.getAllShapes()
+ const allStudies = chart.getAllStudies()
+
+ allShapes.forEach((shape) => {
+ const currentShape = chart.getShapeById(shape.id).getProperties()
+ const currentShapePoints = chart.getShapeById(shape.id).getPoints()
+ if (isAutomaticAddedLine(shape.name, currentShape)) {
+ chart.removeEntity(shape.id)
+ } else {
+ currentShapes.push({
+ points: currentShapePoints,
+ shape: { ...currentShape, shape: shape.name as TradingViewShapeNames },
+ })
+ }
+ })
- if (liquidationPrice) {
- chart.createShape(
- { price: liquidationPrice, time: moment().unix() },
- {
- shape: 'horizontal_line',
- lock: true,
- disableSelection: true,
- text: 'Liquidation',
- zOrder: 'top',
- overrides: {
- linecolor: '#fdb021',
- linestyle: 0,
- linewidth: 1,
- textcolor: '#fdb021',
- showLabel: true,
- },
- },
- )
- }
- if (props.limitOrders) {
- const currentPosition = props.perpsPosition?.amount.isGreaterThan(0) ? 'long' : 'short'
- const positionAmount = props.perpsPosition?.amount || null
+ allStudies.forEach((study) => {
+ currentStudies.push(study.name)
+ })
- props.limitOrders.forEach((order) => {
- const price = order.entryPrice.shiftedBy(oraclePriceDecimalDiff).toNumber()
+ const newTvChartStore = JSON.stringify({
+ ...JSON.parse(tvChartStore),
+ [chartName]: currentShapes,
+ [`${chartName}-studies`]: currentStudies,
+ })
+ setTvChartStore(newTvChartStore)
+ if (entryPrice) {
chart.createShape(
+ { price: entryPrice, time: moment().unix() },
{
- price: price,
- time: moment().unix(),
+ shape: 'horizontal_line',
+ lock: true,
+ disableSelection: true,
+ zOrder: 'top',
+ text: 'Entry',
+ overrides: {
+ linecolor: tradeDirection === 'long' ? upColor : downColor,
+ textcolor: tradeDirection === 'long' ? upColor : downColor,
+ linestyle: 0,
+ linewidth: 1,
+ showLabel: true,
+ },
},
+ )
+ }
+
+ if (liquidationPrice) {
+ chart.createShape(
+ { price: liquidationPrice, time: moment().unix() },
{
shape: 'horizontal_line',
lock: true,
disableSelection: true,
+ text: 'Liquidation',
zOrder: 'top',
- text: getLimitOrderText(order, props.buyAsset, currentPosition, positionAmount),
overrides: {
- linecolor: order.tradeDirection === 'long' ? upColor : downColor,
- textcolor: order.tradeDirection === 'long' ? upColor : downColor,
- showLabel: true,
- linestyle: 2,
+ linecolor: '#fdb021',
+ linestyle: 0,
linewidth: 1,
+ textcolor: '#fdb021',
+ showLabel: true,
},
},
)
- })
+ }
+ if (props.limitOrders) {
+ const currentPosition = props.perpsPosition?.amount.isGreaterThan(0) ? 'long' : 'short'
+ const positionAmount = props.perpsPosition?.amount || null
+
+ props.limitOrders.forEach((order) => {
+ const price = order.entryPrice.shiftedBy(oraclePriceDecimalDiff).toNumber()
+
+ chart.createShape(
+ {
+ price: price,
+ time: moment().unix(),
+ },
+ {
+ shape: 'horizontal_line',
+ lock: true,
+ disableSelection: true,
+ zOrder: 'top',
+ text: getLimitOrderText(order, props.buyAsset, currentPosition, positionAmount),
+ overrides: {
+ linecolor: order.tradeDirection === 'long' ? upColor : downColor,
+ textcolor: order.tradeDirection === 'long' ? upColor : downColor,
+ showLabel: true,
+ linestyle: 2,
+ linewidth: 1,
+ },
+ },
+ )
+ })
+ }
+ } catch (e) {
+ console.info('Error on updating chart', e)
+ return
}
}, [
chartName,
@@ -335,15 +363,15 @@ export default function TradeChart(props: Props) {
useEffect(() => {
if (!chartWidget) return
chartWidget.onChartReady(() => {
- updateShapes()
+ updateShapesAndStudies()
chartWidget
.activeChart()
.onIntervalChanged()
.subscribe(null, () => {
- updateShapes()
+ updateShapesAndStudies()
})
})
- }, [updateShapes])
+ }, [updateShapesAndStudies])
return (
{
- if (!account) return [[], []]
+ if (!account) return [[], assets]
const activePerpsPositions = assets.filter((assets) =>
- account?.perps?.find((perp) => perp.denom === assets.denom),
+ account.perps?.find((perp) => perp.denom === assets.denom),
)
const availablePerpsMarkets = assets.filter(
(assets) => !activePerpsPositions.find((perp) => perp.denom === assets.denom),
diff --git a/src/constants/defaultSettings.ts b/src/constants/defaultSettings.ts
index 863b68c62..ac4c28cd2 100644
--- a/src/constants/defaultSettings.ts
+++ b/src/constants/defaultSettings.ts
@@ -1,6 +1,4 @@
-import { BN_ZERO_ONE } from 'constants/math'
import { ORACLE_DENOM } from 'constants/oracle'
-import { BNCoin } from 'types/classes/BNCoin'
import { RewardsCenterType } from 'types/enums'
import { ResolutionString } from 'utils/charting_library'
@@ -22,7 +20,8 @@ export const getDefaultChainSettings = (chainConfig: ChainConfig) => {
theme: 'default',
rewardsCenterType: RewardsCenterType.Token,
showSummary: true,
- perpsKeeperFee: BNCoin.fromDenomAndBigNumber('usd', BN_ZERO_ONE).toCoin(),
tvChartStore: JSON.stringify({}),
+ showPerpsVaultBanner: true,
+ fundingRateInterval: '1H',
}
}
diff --git a/src/constants/localStorageKeys.ts b/src/constants/localStorageKeys.ts
index 86e0b9308..90699946e 100644
--- a/src/constants/localStorageKeys.ts
+++ b/src/constants/localStorageKeys.ts
@@ -26,4 +26,6 @@ export enum LocalStorageKeys {
REWARDS_CENTER_TYPE = 'rewardsCenterType',
SHOW_SUMMARY = 'showSummary',
TV_CHART_STORE = 'tvChartStore',
+ SHOW_PERPS_VAULT_BANNER = 'showPerpsVaultBanner',
+ FUNDING_RATE_INTERVAL = 'fundingRateInterval',
}
diff --git a/src/constants/math.ts b/src/constants/math.ts
index 16601f990..914cb1c9b 100644
--- a/src/constants/math.ts
+++ b/src/constants/math.ts
@@ -2,7 +2,6 @@ import { BN } from 'utils/helpers'
export const BN_ZERO = BN(0)
export const BN_ONE = BN(1)
-export const BN_ZERO_ONE = BN(0.1)
export const MIN_AMOUNT = 0.000001
export const MAX_AMOUNT_DECIMALS = 6
diff --git a/src/hooks/chain/useChainConfig.ts b/src/hooks/chain/useChainConfig.ts
index 1e3f8cd77..4c00b0e95 100644
--- a/src/hooks/chain/useChainConfig.ts
+++ b/src/hooks/chain/useChainConfig.ts
@@ -1,23 +1,47 @@
import chains from 'chains'
import { LocalStorageKeys } from 'constants/localStorageKeys'
import { getCurrentChainId } from 'utils/getCurrentChainId'
+import useCreditManagerConfig from 'hooks/chain/useCreditManagerConfig'
+import { setNodeError } from 'utils/error'
export default function useChainConfig() {
const chainId = getCurrentChainId()
+ const baseConfig = chains[chainId]
+ const { data: creditManagerConfig, error } = useCreditManagerConfig()
const rpcEndpoint =
- localStorage.getItem(`${chainId}/${LocalStorageKeys.RPC_ENDPOINT}`) ??
- chains[chainId].endpoints.rpc
+ localStorage.getItem(`${chainId}/${LocalStorageKeys.RPC_ENDPOINT}`) ?? baseConfig.endpoints.rpc
const restEndpoint =
localStorage.getItem(`${chainId}/${LocalStorageKeys.REST_ENDPOINT}`) ??
- chains[chainId].endpoints.rest
+ baseConfig.endpoints.rest
+
+ if (error || !creditManagerConfig) {
+ return {
+ ...baseConfig,
+ endpoints: {
+ ...baseConfig.endpoints,
+ rpc: rpcEndpoint,
+ rest: restEndpoint,
+ },
+ contracts: baseConfig.contracts,
+ }
+ }
return {
- ...chains[chainId],
+ ...baseConfig,
endpoints: {
- ...chains[chainId].endpoints,
+ ...baseConfig.endpoints,
rpc: rpcEndpoint,
rest: restEndpoint,
},
+ contracts: {
+ ...baseConfig.contracts,
+ accountNft: creditManagerConfig.account_nft,
+ oracle: creditManagerConfig.oracle,
+ params: creditManagerConfig.params,
+ redBank: creditManagerConfig.red_bank,
+ incentives: creditManagerConfig.incentives,
+ perps: creditManagerConfig.perps,
+ },
}
}
diff --git a/src/hooks/chain/useCreditManagerConfig.ts b/src/hooks/chain/useCreditManagerConfig.ts
new file mode 100644
index 000000000..bc77418da
--- /dev/null
+++ b/src/hooks/chain/useCreditManagerConfig.ts
@@ -0,0 +1,61 @@
+import { CosmWasmClient } from '@cosmjs/cosmwasm-stargate'
+import useSWRImmutable from 'swr/immutable'
+import { getUrl } from 'utils/url'
+import useStore from 'store'
+import { getCurrentChainId } from 'utils/getCurrentChainId'
+import chains from 'chains'
+import { setNodeError } from 'utils/error'
+
+export default function useCreditManagerConfig() {
+ const chainId = getCurrentChainId()
+ const baseConfig = chains[chainId]
+
+ if (!baseConfig.contracts.creditManager) {
+ throw new Error('Credit manager contract address is required')
+ }
+
+ return useSWRImmutable(
+ baseConfig.contracts.creditManager && `chains/${chainId}/creditManager/config`,
+ async () => {
+ try {
+ const client = await CosmWasmClient.connect(getUrl(baseConfig.endpoints.rpc))
+ const config = await client.queryContractSmart(baseConfig.contracts.creditManager, {
+ config: {},
+ })
+
+ if (!config.account_nft || !config.oracle || !config.params || !config.red_bank) {
+ const error = new Error('Credit manager config missing required fields')
+ setNodeError(getUrl(baseConfig.endpoints.rpc), error.message)
+ throw error
+ }
+
+ useStore.setState({
+ creditManagerConfig: {
+ ...config,
+ credit_manager_contract_addr: baseConfig.contracts.creditManager,
+ account_nft: config.account_nft,
+ oracle: config.oracle,
+ params: config.params,
+ red_bank: config.red_bank,
+ incentives: config.incentives,
+ perps: config.perps,
+ },
+ errorStore: { nodeError: null, apiError: null },
+ })
+
+ return config
+ } catch (ex) {
+ const error = ex instanceof Error ? ex : new Error('Unknown Error')
+ setNodeError(getUrl(baseConfig.endpoints.rpc), error.message)
+ throw error
+ }
+ },
+ {
+ suspense: true,
+ revalidateOnFocus: false,
+ revalidateOnReconnect: false,
+ revalidateIfStale: false,
+ keepPreviousData: false,
+ },
+ )
+}
diff --git a/src/hooks/health-computer/useHealthComputer.ts b/src/hooks/health-computer/useHealthComputer.ts
index 074b590c4..b8e95dfc3 100644
--- a/src/hooks/health-computer/useHealthComputer.ts
+++ b/src/hooks/health-computer/useHealthComputer.ts
@@ -300,7 +300,7 @@ export default function useHealthComputer(account?: Account) {
return null
}
},
- [healthComputer, perpsAssets],
+ [healthComputer, perpsAssets, whitelistedAssets],
)
const computeMaxPerpAmount = useCallback(
diff --git a/src/hooks/perps/usePerpsLimitOrdersRows.ts b/src/hooks/perps/usePerpsLimitOrdersRows.ts
index 8628050e5..6c6b7e879 100644
--- a/src/hooks/perps/usePerpsLimitOrdersRows.ts
+++ b/src/hooks/perps/usePerpsLimitOrdersRows.ts
@@ -11,7 +11,6 @@ export default function usePerpsLimitOrderRows() {
const perpAssets = usePerpsEnabledAssets()
const { data: limitOrders } = usePerpsLimitOrders()
const { data: perpsConfig } = usePerpsConfig()
-
const { computeLiquidationPrice } = useHealthComputer(currentAccount)
return useMemo(() => {
diff --git a/src/hooks/perps/usePerpsMarket.ts b/src/hooks/perps/usePerpsMarket.ts
index db9a47633..6273d2b44 100644
--- a/src/hooks/perps/usePerpsMarket.ts
+++ b/src/hooks/perps/usePerpsMarket.ts
@@ -3,21 +3,32 @@ import { useMemo } from 'react'
import usePerpsAsset from 'hooks/perps/usePerpsAsset'
import usePerpsMarketState from 'hooks/perps/usePerpsMarketState'
import { BN } from 'utils/helpers'
+import { BN_ZERO } from 'constants/math'
export default function usePerpsMarket() {
const { perpsAsset } = usePerpsAsset()
-
const perpsMarketState = usePerpsMarketState()
return useMemo(() => {
if (!perpsMarketState) return null
+
+ const longOI = BN(perpsMarketState.long_oi)
+ const shortOI = BN(perpsMarketState.short_oi)
+ const totalOI = longOI.plus(shortOI)
+
+ const skewPercentage = totalOI.isZero()
+ ? BN_ZERO
+ : longOI.minus(shortOI).div(totalOI).shiftedBy(2)
+
return {
// Funding rate is per 24h
- fundingRate: BN(perpsMarketState.current_funding_rate as any).times(100),
+ fundingRate: BN(perpsMarketState.current_funding_rate as any).shiftedBy(2),
asset: perpsAsset,
openInterest: {
- long: BN(perpsMarketState.long_oi),
- short: BN(perpsMarketState.short_oi),
+ long: longOI,
+ short: shortOI,
+ total: totalOI,
+ skewPercentage: skewPercentage,
},
} as PerpsMarket
}, [perpsAsset, perpsMarketState])
diff --git a/src/hooks/perps/usePerpsOrderForm.ts b/src/hooks/perps/usePerpsOrderForm.ts
index f0c8fc31d..c9f250927 100644
--- a/src/hooks/perps/usePerpsOrderForm.ts
+++ b/src/hooks/perps/usePerpsOrderForm.ts
@@ -4,27 +4,37 @@ import { OrderType } from 'types/enums'
interface PerpsOrderFormState {
limitPrice: BigNumber
+ stopPrice: BigNumber
orderType: 'market' | 'limit' | 'stop'
selectedOrderType: OrderType
setLimitPrice: (price: BigNumber, fromTradingView?: boolean) => void
- setOrderType: (type: 'market' | 'limit') => void
+ setStopPrice: (price: BigNumber, fromTradingView?: boolean) => void
+ setOrderType: (type: 'market' | 'limit' | 'stop') => void
+ setSelectedOrderType: (type: OrderType) => void
+}
+
+interface PerpsOrderFormState {
+ limitPrice: BigNumber
+ stopPrice: BigNumber
+ orderType: 'market' | 'limit' | 'stop'
+ selectedOrderType: OrderType
+ setLimitPrice: (price: BigNumber, fromTradingView?: boolean) => void
+ setStopPrice: (price: BigNumber, fromTradingView?: boolean) => void
+ setOrderType: (type: 'market' | 'limit' | 'stop') => void
setSelectedOrderType: (type: OrderType) => void
}
export const usePerpsOrderForm = create((set) => ({
limitPrice: new BigNumber(0),
+ stopPrice: new BigNumber(0),
orderType: 'market',
selectedOrderType: OrderType.MARKET,
setLimitPrice: (price, fromTradingView = false) => {
if (fromTradingView) {
set({
limitPrice: price,
- ...(fromTradingView
- ? {
- orderType: 'limit',
- selectedOrderType: OrderType.LIMIT,
- }
- : {}),
+ orderType: 'limit',
+ selectedOrderType: OrderType.LIMIT,
})
} else {
set({
@@ -32,12 +42,30 @@ export const usePerpsOrderForm = create((set) => ({
})
}
},
+ setStopPrice: (price, fromTradingView = false) => {
+ if (fromTradingView) {
+ set({
+ stopPrice: price,
+ orderType: 'stop',
+ selectedOrderType: OrderType.STOP,
+ })
+ } else {
+ set({
+ stopPrice: price,
+ })
+ }
+ },
setOrderType: (type) => set({ orderType: type }),
setSelectedOrderType: (type) => {
set((state) => ({
selectedOrderType: type,
- orderType: type === OrderType.MARKET ? 'market' : 'limit',
- ...(type === OrderType.MARKET ? { limitPrice: new BigNumber(0) } : {}),
+ orderType: type === OrderType.MARKET ? 'market' : type === OrderType.LIMIT ? 'limit' : 'stop',
+ ...(type === OrderType.MARKET
+ ? {
+ limitPrice: new BigNumber(0),
+ stopPrice: new BigNumber(0),
+ }
+ : {}),
}))
},
}))
diff --git a/src/hooks/perps/useSubmitLimitOrder.ts b/src/hooks/perps/useSubmitLimitOrder.ts
index bec5b14be..b2795b3de 100644
--- a/src/hooks/perps/useSubmitLimitOrder.ts
+++ b/src/hooks/perps/useSubmitLimitOrder.ts
@@ -86,7 +86,7 @@ export function useSubmitLimitOrder() {
keeperFee,
tradeDirection,
price: adjustedLimitPrice,
- reduceOnly: isReduceOnly,
+ isReduceOnly,
comparison,
}
},
diff --git a/src/pages/PortfolioAccountPage.tsx b/src/pages/PortfolioAccountPage.tsx
index 6f0836fa3..8cbe9a81a 100644
--- a/src/pages/PortfolioAccountPage.tsx
+++ b/src/pages/PortfolioAccountPage.tsx
@@ -34,7 +34,7 @@ export default function PortfolioAccountPage() {
{isUsersAccount && }
- {chainConfig.farm && }
+ {(chainConfig.farm || chainConfig.perps) && }
{chainConfig.perps && }
diff --git a/src/store/slices/broadcast.ts b/src/store/slices/broadcast.ts
index 2edfdd045..dd1439ff0 100644
--- a/src/store/slices/broadcast.ts
+++ b/src/store/slices/broadcast.ts
@@ -244,6 +244,7 @@ export default function createBroadcastSlice(
const cmContract = get().chainConfig.contracts.creditManager
const nftContract = get().chainConfig.contracts.accountNft
+ if (!nftContract) return false
const response = get().executeMsg({
messages: [
generateExecutionMessage(get().address, cmContract, refundMessage, []),
@@ -329,6 +330,7 @@ export default function createBroadcastSlice(
? get().chainConfig.contracts.incentives
: get().chainConfig.contracts.creditManager
+ if (!contract) return false
const response = get().executeMsg({
messages: [
generateExecutionMessage(
@@ -1173,6 +1175,7 @@ export default function createBroadcastSlice(
const redBankContract = get().chainConfig.contracts.redBank
+ if (!redBankContract) return false
const response = get().executeMsg({
messages: [generateExecutionMessage(get().address, redBankContract, msg, sortFunds(funds))],
})
diff --git a/src/store/slices/common.ts b/src/store/slices/common.ts
index bb1977124..5d6abacc7 100644
--- a/src/store/slices/common.ts
+++ b/src/store/slices/common.ts
@@ -22,5 +22,6 @@ export default function createCommonSlice(set: SetState