share position modal
This commit is contained in:
parent
0ddcf8c2c2
commit
f4ba160686
|
@ -8,7 +8,7 @@ const MenuItem = ({ href, children, newWindow = false }) => {
|
|||
return (
|
||||
<Link href={href} shallow={true}>
|
||||
<a
|
||||
className={`border-b border-th-bkg-4 md:border-none flex justify-between text-th-fgd-1 font-bold items-center md:px-1 py-3 md:py-0 hover:text-th-primary
|
||||
className={`h-full border-b border-th-bkg-4 md:border-none flex justify-between text-th-fgd-1 font-bold items-center md:px-2 lg:px-4 py-3 md:py-0 hover:text-th-primary
|
||||
${asPath === href ? `text-th-primary` : `border-transparent`}
|
||||
`}
|
||||
target={newWindow ? '_blank' : ''}
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
import React from 'react'
|
||||
import { Portal } from 'react-portal'
|
||||
import { XIcon } from '@heroicons/react/outline'
|
||||
|
||||
const Modal = ({
|
||||
isOpen,
|
||||
onClose,
|
||||
children,
|
||||
hideClose = false,
|
||||
noPadding = false,
|
||||
alignTop = false,
|
||||
}) => {
|
||||
const Modal: any = React.forwardRef<any, any>((props, ref) => {
|
||||
const {
|
||||
isOpen,
|
||||
onClose,
|
||||
children,
|
||||
hideClose = false,
|
||||
noPadding = false,
|
||||
alignTop = false,
|
||||
className = '',
|
||||
} = props
|
||||
|
||||
return (
|
||||
<Portal>
|
||||
<div
|
||||
|
@ -40,7 +44,8 @@ const Modal = ({
|
|||
className={`inline-block bg-th-bkg-2 min-h-screen sm:min-h-full
|
||||
sm:rounded-lg text-left ${
|
||||
noPadding ? '' : 'px-8 pt-6 pb-6'
|
||||
} shadow-lg transform transition-all align-middle sm:max-w-md w-full`}
|
||||
} shadow-lg transform transition-all align-middle sm:max-w-md w-full ${className}`}
|
||||
ref={ref}
|
||||
>
|
||||
{!hideClose ? (
|
||||
<div className="">
|
||||
|
@ -59,7 +64,7 @@ const Modal = ({
|
|||
</div>
|
||||
</Portal>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
const Header = ({ children }) => {
|
||||
return (
|
||||
|
|
|
@ -1,9 +1,17 @@
|
|||
import { useRef, useState } from 'react'
|
||||
import { Popover } from '@headlessui/react'
|
||||
import { DotsHorizontalIcon } from '@heroicons/react/solid'
|
||||
import Link from 'next/link'
|
||||
import { ChevronDownIcon } from '@heroicons/react/outline'
|
||||
|
||||
export default function NavDropMenu({ menuTitle = '', linksArray = [] }) {
|
||||
type NavDropMenuProps = {
|
||||
menuTitle: string | React.ReactNode
|
||||
linksArray: [string, string, boolean][]
|
||||
}
|
||||
|
||||
export default function NavDropMenu({
|
||||
menuTitle = '',
|
||||
linksArray = [],
|
||||
}: NavDropMenuProps) {
|
||||
const buttonRef = useRef(null)
|
||||
const [openState, setOpenState] = useState(false)
|
||||
|
||||
|
@ -34,20 +42,23 @@ export default function NavDropMenu({ menuTitle = '', linksArray = [] }) {
|
|||
onMouseLeave={() => onHover(open, 'onMouseLeave')}
|
||||
className="flex flex-col"
|
||||
>
|
||||
<Popover.Button className="h-10 focus:outline-none" ref={buttonRef}>
|
||||
<Popover.Button
|
||||
className="h-10 text-th-fgd-1 hover:text-th-primary md:px-2 lg:px-4 focus:outline-none"
|
||||
ref={buttonRef}
|
||||
>
|
||||
<div
|
||||
className="flex items-center text-th-fgd-1 hover:text-th-primary"
|
||||
className="flex items-center"
|
||||
onClick={() => handleClick(open)}
|
||||
>
|
||||
<span className="font-bold">{menuTitle}</span>
|
||||
<DotsHorizontalIcon
|
||||
<ChevronDownIcon
|
||||
className="h-4 w-4 default-transition ml-1.5"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
</Popover.Button>
|
||||
<Popover.Panel className="absolute top-10 z-10">
|
||||
<div className="relative bg-th-bkg-2 divide-y divide-th-bkg-3 px-4 rounded">
|
||||
<div className="relative bg-th-bkg-1 divide-y divide-th-bkg-3 px-4 rounded">
|
||||
{linksArray.map(([name, href, isExternal]) =>
|
||||
!isExternal ? (
|
||||
<Link href={href} key={href}>
|
||||
|
|
|
@ -5,7 +5,7 @@ import { useTranslation } from 'next-i18next'
|
|||
import { ExclamationIcon } from '@heroicons/react/outline'
|
||||
|
||||
import useMangoStore from '../stores/useMangoStore'
|
||||
import Button from '../components/Button'
|
||||
import Button, { LinkButton } from '../components/Button'
|
||||
import { useViewport } from '../hooks/useViewport'
|
||||
import { breakpoints } from './TradePageGrid'
|
||||
import { ExpandableRow, Table, Td, Th, TrBody, TrHead } from './TableElements'
|
||||
|
@ -16,16 +16,19 @@ import PerpSideBadge from './PerpSideBadge'
|
|||
import PnlText from './PnlText'
|
||||
import { settlePnl } from './MarketPosition'
|
||||
import MobileTableHeader from './mobile/MobileTableHeader'
|
||||
import ShareModal from './ShareModal'
|
||||
import { TwitterIcon } from './icons'
|
||||
import { marketSelector } from '../stores/selectors'
|
||||
|
||||
const PositionsTable = () => {
|
||||
const { t } = useTranslation('common')
|
||||
const { reloadMangoAccount } = useMangoStore((s) => s.actions)
|
||||
const [settling, setSettling] = useState(false)
|
||||
|
||||
const selectedMarket = useMangoStore((s) => s.selectedMarket.current)
|
||||
const selectedMarketConfig = useMangoStore((s) => s.selectedMarket.config)
|
||||
const price = useMangoStore((s) => s.tradeForm.price)
|
||||
const [showShareModal, setShowShareModal] = useState(false)
|
||||
const [showMarketCloseModal, setShowMarketCloseModal] = useState(false)
|
||||
|
||||
const market = useMangoStore(marketSelector)
|
||||
const price = useMangoStore((s) => s.tradeForm.price)
|
||||
const setMangoStore = useMangoStore((s) => s.set)
|
||||
const openPositions = useMangoStore(
|
||||
(s) => s.selectedMangoAccount.openPerpPositions
|
||||
|
@ -41,7 +44,7 @@ const PositionsTable = () => {
|
|||
}, [])
|
||||
|
||||
const handleSizeClick = (size, side, indexPrice) => {
|
||||
const step = selectedMarket.minOrderSize
|
||||
const step = market.minOrderSize
|
||||
const priceOrDefault = price ? price : indexPrice
|
||||
const roundedSize = Math.round(size / step) * step
|
||||
const quoteSize = roundedSize * priceOrDefault
|
||||
|
@ -62,6 +65,10 @@ const PositionsTable = () => {
|
|||
setSettling(false)
|
||||
}
|
||||
|
||||
const handleCloseShare = useCallback(() => {
|
||||
setShowShareModal(false)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="flex flex-col pb-2">
|
||||
{unsettledPositions.length > 0 ? (
|
||||
|
@ -170,7 +177,7 @@ const PositionsTable = () => {
|
|||
</Td>
|
||||
<Td>
|
||||
{basePosition &&
|
||||
selectedMarketConfig.kind === 'perp' &&
|
||||
marketConfig.kind === 'perp' &&
|
||||
asPath.includes(marketConfig.baseSymbol) ? (
|
||||
<span
|
||||
className="cursor-pointer underline hover:no-underline"
|
||||
|
@ -212,6 +219,14 @@ const PositionsTable = () => {
|
|||
'--'
|
||||
)}
|
||||
</Td>
|
||||
<Td>
|
||||
<LinkButton
|
||||
onClick={() => setShowShareModal(true)}
|
||||
disabled={!avgEntryPrice}
|
||||
>
|
||||
<TwitterIcon className="h-4 w-4" />
|
||||
</LinkButton>
|
||||
</Td>
|
||||
{showMarketCloseModal ? (
|
||||
<MarketCloseModal
|
||||
isOpen={showMarketCloseModal}
|
||||
|
@ -220,6 +235,20 @@ const PositionsTable = () => {
|
|||
marketIndex={marketConfig.marketIndex}
|
||||
/>
|
||||
) : null}
|
||||
{showShareModal ? (
|
||||
<ShareModal
|
||||
isOpen={showShareModal}
|
||||
onClose={handleCloseShare}
|
||||
position={{
|
||||
marketConfig,
|
||||
indexPrice,
|
||||
avgEntryPrice: avgEntryPrice
|
||||
? avgEntryPrice
|
||||
: '0.00',
|
||||
basePosition,
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
</TrBody>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,181 @@
|
|||
import {
|
||||
FunctionComponent,
|
||||
useEffect,
|
||||
useMemo,
|
||||
createRef,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { getWeights, MarketConfig } from '@blockworks-foundation/mango-client'
|
||||
|
||||
import useMangoStore from '../stores/useMangoStore'
|
||||
import Modal from './Modal'
|
||||
import { useScreenshot } from '../hooks/useScreenshot'
|
||||
import { ExternalLinkIcon } from '@heroicons/react/outline'
|
||||
|
||||
interface ShareModalProps {
|
||||
onClose: () => void
|
||||
isOpen: boolean
|
||||
position: {
|
||||
indexPrice: number
|
||||
avgEntryPrice: number
|
||||
basePosition: number
|
||||
marketConfig: MarketConfig
|
||||
}
|
||||
}
|
||||
|
||||
const ShareModal: FunctionComponent<ShareModalProps> = ({
|
||||
isOpen,
|
||||
onClose,
|
||||
position,
|
||||
}) => {
|
||||
const ref = createRef()
|
||||
const [copied, setCopied] = useState(false)
|
||||
const [showButton, setShowButton] = useState(true)
|
||||
const marketConfig = position.marketConfig
|
||||
const mangoGroup = useMangoStore((s) => s.selectedMangoGroup.current)
|
||||
const [image, takeScreenshot] = useScreenshot()
|
||||
|
||||
const initLeverage = useMemo(() => {
|
||||
if (!mangoGroup || !marketConfig) return 1
|
||||
|
||||
const ws = getWeights(mangoGroup, marketConfig.marketIndex, 'Init')
|
||||
return Math.round((100 * -1) / (ws.perpAssetWeight.toNumber() - 1)) / 100
|
||||
}, [mangoGroup, marketConfig])
|
||||
|
||||
const positionPercentage =
|
||||
((position.indexPrice - position.avgEntryPrice) / position.avgEntryPrice) *
|
||||
100 *
|
||||
initLeverage
|
||||
|
||||
const side = position.basePosition > 0 ? 'LONG' : 'SHORT'
|
||||
|
||||
async function copyToClipboard(image) {
|
||||
try {
|
||||
image.toBlob((blob) => {
|
||||
navigator.clipboard.write([new ClipboardItem({ 'image/png': blob })])
|
||||
}, 'image/png')
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (image) {
|
||||
copyToClipboard(image)
|
||||
setCopied(true)
|
||||
setShowButton(true)
|
||||
}
|
||||
}, [image])
|
||||
|
||||
useEffect(() => {
|
||||
// if the button is hidden we are taking a screenshot
|
||||
if (!showButton) {
|
||||
takeScreenshot(ref.current)
|
||||
}
|
||||
}, [showButton])
|
||||
|
||||
const handleCopyToClipboard = () => {
|
||||
setShowButton(false)
|
||||
}
|
||||
|
||||
const isProfit = positionPercentage > 0
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
className="md:max-w-sm"
|
||||
noPadding
|
||||
hideClose
|
||||
ref={ref}
|
||||
>
|
||||
<div className="relative overflow-hidden px-8 pt-6 pb-6 rounded-lg">
|
||||
<div id="share-image" className="relative z-20">
|
||||
<div className="flex justify-center p-4 pt-0">
|
||||
<img
|
||||
className={`h-32 w-auto`}
|
||||
src="/assets/icons/logo.svg"
|
||||
alt="next"
|
||||
/>
|
||||
</div>
|
||||
<div className="text-th-fgd-1 text-center text-xl">
|
||||
<span className="font-bold">Mango</span>
|
||||
<span className="font-extralight"> Markets</span>
|
||||
</div>
|
||||
<div className="pb-4 text-lg text-center">
|
||||
<span className="text-th-fgd-3">{position.marketConfig.name}</span>
|
||||
<span className="px-2 text-th-fgd-4">|</span>
|
||||
|
||||
<span
|
||||
className={`${
|
||||
position.basePosition > 0 ? 'text-th-green' : 'text-th-red'
|
||||
}`}
|
||||
>
|
||||
{side}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-center items-center">
|
||||
<div
|
||||
className={`border mb-6 px-4 ${
|
||||
!showButton ? 'pt-2' : 'py-2'
|
||||
} rounded-lg text-5xl text-center font-light ${
|
||||
isProfit
|
||||
? 'border-th-green text-th-green'
|
||||
: 'border-th-red text-th-red'
|
||||
}`}
|
||||
>
|
||||
{isProfit
|
||||
? `${positionPercentage.toFixed(2)}`
|
||||
: positionPercentage.toFixed(2)}
|
||||
%
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-2 text-th-fgd-1">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-th-fgd-2">Avg Entry Price:</span>
|
||||
<span>${position.avgEntryPrice.toFixed(2)}</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-th-fgd-2">Mark Price:</span>
|
||||
<span>${position.indexPrice.toFixed(2)}</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-th-fgd-2">Max Leverage:</span>
|
||||
<span>{initLeverage}x</span>
|
||||
</div>
|
||||
</div>
|
||||
{copied ? (
|
||||
<a
|
||||
className="bg-th-bkg-3 hover:cursor-pointer block mt-6 px-4 py-3 rounded-full text-center text-th-fgd-1 w-full"
|
||||
href={`https://twitter.com/intent/tweet?text=I'm ${side} %24${position.marketConfig.baseSymbol} perp on %40mangomarkets%0A[PASTE IMAGE HERE]`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<div className="flex items-center justify-center">
|
||||
<div>Tweet</div>
|
||||
<ExternalLinkIcon className="ml-1 h-4 w-4" />
|
||||
</div>
|
||||
</a>
|
||||
) : (
|
||||
<a
|
||||
className={`${
|
||||
!showButton ? 'hidden' : ''
|
||||
} bg-th-bkg-3 hover:cursor-pointer block mt-6 px-4 py-3 rounded-full text-center text-th-fgd-1 w-full`}
|
||||
onClick={handleCopyToClipboard}
|
||||
>
|
||||
Copy Image to Clipboard & Share
|
||||
</a>
|
||||
)}
|
||||
{!showButton ? <div className="mb-6">.</div> : null}
|
||||
</div>
|
||||
<div
|
||||
className={`absolute h-full w-full opacity-75 bottom-2/3 left-0 pointer-events-none bg-gradient-to-b ${
|
||||
isProfit ? 'from-th-green' : 'from-th-red'
|
||||
} to-th-bkg-2 z-10`}
|
||||
></div>
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
export default ShareModal
|
|
@ -13,11 +13,11 @@ import { DEFAULT_MARKET_KEY, initialMarket } from './SettingsModal'
|
|||
import { useTranslation } from 'next-i18next'
|
||||
import Settings from './Settings'
|
||||
|
||||
const StyledNewLabel = ({ children, ...props }) => (
|
||||
<div style={{ fontSize: '0.5rem', marginLeft: '1px' }} {...props}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
// const StyledNewLabel = ({ children, ...props }) => (
|
||||
// <div style={{ fontSize: '0.5rem', marginLeft: '1px' }} {...props}>
|
||||
// {children}
|
||||
// </div>
|
||||
// )
|
||||
|
||||
const TopBar = () => {
|
||||
const { t } = useTranslation('common')
|
||||
|
@ -50,58 +50,22 @@ const TopBar = () => {
|
|||
/>
|
||||
</div>
|
||||
</Link>
|
||||
<div
|
||||
className={`hidden md:flex md:items-center md:space-x-4 lg:space-x-6 md:ml-4`}
|
||||
>
|
||||
<div className={`hidden md:flex md:items-center md:ml-4`}>
|
||||
<MenuItem href={defaultMarket.path}>{t('trade')}</MenuItem>
|
||||
<MenuItem href="/swap">{t('swap')}</MenuItem>
|
||||
<MenuItem href="/account">{t('account')}</MenuItem>
|
||||
<MenuItem href="/borrow">{t('borrow')}</MenuItem>
|
||||
<div className="relative">
|
||||
<MenuItem href="/risk-calculator">
|
||||
{t('calculator')}
|
||||
<div>
|
||||
<div className="absolute flex items-center justify-center h-4 px-1.5 bg-gradient-to-br from-red-500 to-yellow-500 rounded-full -right-5 -top-3">
|
||||
<StyledNewLabel className="text-white uppercase">
|
||||
new
|
||||
</StyledNewLabel>
|
||||
</div>
|
||||
</div>
|
||||
</MenuItem>
|
||||
</div>
|
||||
<MenuItem href="/stats">{t('stats')}</MenuItem>
|
||||
<MenuItem href="https://docs.mango.markets/" newWindow>
|
||||
{t('learn')}
|
||||
</MenuItem>
|
||||
<NavDropMenu
|
||||
menuTitle={t('more')}
|
||||
// linksArray: [name: string, href: string, isExternal: boolean]
|
||||
linksArray={[
|
||||
['Mango v1', 'https://v1.mango.markets', true],
|
||||
[t('calculator'), '/risk-calculator', false],
|
||||
[t('learn'), 'https://docs.mango.markets/', true],
|
||||
['Mango v2', 'https://v2.mango.markets', true],
|
||||
['Mango v1', 'https://v1.mango.markets', true],
|
||||
]}
|
||||
/>
|
||||
{/* <button
|
||||
onClick={() => {
|
||||
handleLocaleChange('en')
|
||||
}}
|
||||
>
|
||||
English
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
handleLocaleChange('zh')
|
||||
}}
|
||||
>
|
||||
简体中文
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
handleLocaleChange('zh_tw')
|
||||
}}
|
||||
>
|
||||
繁體中文
|
||||
</button> */}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
|
|
|
@ -121,6 +121,24 @@ export const TelegramIcon = ({ className }) => {
|
|||
)
|
||||
}
|
||||
|
||||
export const TwitterIcon = ({ className }) => {
|
||||
return (
|
||||
<svg
|
||||
className={`${className}`}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
>
|
||||
<path d="M23 3a10.9 10.9 0 0 1-3.14 1.53 4.48 4.48 0 0 0-7.86 3v1A10.66 10.66 0 0 1 3 4s-4 9 5 13a11.64 11.64 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0-.08-.83A7.72 7.72 0 0 0 23 3z"></path>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export const ProfileIcon = ({ className }) => {
|
||||
return (
|
||||
<svg
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
import { useState } from 'react'
|
||||
import html2canvas from 'html2canvas'
|
||||
|
||||
/**
|
||||
* @module Main_Hook
|
||||
* Hook return
|
||||
* @typedef {Array} HookReturn
|
||||
* @property {string} HookReturn[0] - image string
|
||||
* @property {string} HookReturn[1] - take screen shot string
|
||||
* @property {object} HookReturn[2] - errors
|
||||
*/
|
||||
|
||||
/**
|
||||
* hook for creating screenshot from html node
|
||||
* @returns {HookReturn}
|
||||
*/
|
||||
const useScreenshot = () => {
|
||||
const [image, setImage] = useState(null)
|
||||
const [error, setError] = useState(null)
|
||||
/**
|
||||
* convert html node to image
|
||||
* @param {HTMLElement} node
|
||||
*/
|
||||
const takeScreenShot = (node) => {
|
||||
if (!node) {
|
||||
throw new Error('You should provide correct html node.')
|
||||
}
|
||||
return html2canvas(node)
|
||||
.then((canvas) => {
|
||||
const croppedCanvas = document.createElement('canvas')
|
||||
const croppedCanvasContext = croppedCanvas.getContext('2d')
|
||||
// init data
|
||||
const cropPositionTop = 0
|
||||
const cropPositionLeft = 0
|
||||
const cropWidth = canvas.width
|
||||
const cropHeight = canvas.height
|
||||
|
||||
croppedCanvas.width = cropWidth
|
||||
croppedCanvas.height = cropHeight
|
||||
|
||||
croppedCanvasContext.drawImage(
|
||||
canvas,
|
||||
cropPositionLeft,
|
||||
cropPositionTop
|
||||
)
|
||||
|
||||
setImage(croppedCanvas)
|
||||
return croppedCanvas
|
||||
})
|
||||
.catch(setError)
|
||||
}
|
||||
|
||||
return [
|
||||
image,
|
||||
takeScreenShot,
|
||||
{
|
||||
error,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* creates name of file
|
||||
* @param {string} extension
|
||||
* @param {string[]} parts of file name
|
||||
*/
|
||||
const createFileName = (extension = '', ...names) => {
|
||||
if (!extension) {
|
||||
return ''
|
||||
}
|
||||
|
||||
return `${names.join('')}.${extension}`
|
||||
}
|
||||
|
||||
export { useScreenshot, createFileName }
|
|
@ -38,6 +38,7 @@
|
|||
"buffer-layout": "^1.2.0",
|
||||
"dayjs": "^1.10.4",
|
||||
"export-to-csv": "^0.2.1",
|
||||
"html2canvas": "^1.4.1",
|
||||
"immer": "^9.0.1",
|
||||
"intro.js": "^4.2.2",
|
||||
"intro.js-react": "^0.5.0",
|
||||
|
|
|
@ -172,7 +172,7 @@
|
|||
"languages-tip-title": "Multilingual?",
|
||||
"layout-tip-desc": "Unlock to re-arrange and re-size the trading panels to your liking.",
|
||||
"layout-tip-title": "Customize Layout",
|
||||
"learn": "Learn",
|
||||
"learn": "Documentation",
|
||||
"learn-more": "Learn more",
|
||||
"lets-go": "Let's Go",
|
||||
"leverage": "Leverage",
|
||||
|
|
|
@ -522,14 +522,28 @@ const useMangoStore = create<MangoStore>((set, get) => {
|
|||
const set = get().set
|
||||
if (!selectedMangoAccount) return
|
||||
|
||||
let serumTradeHistory = []
|
||||
fetch(
|
||||
`https://event-history-api.herokuapp.com/perp_trades/${selectedMangoAccount.publicKey.toString()}`
|
||||
)
|
||||
.then((response) => response.json())
|
||||
.then((jsonPerpHistory) => {
|
||||
const perpHistory = jsonPerpHistory?.data || []
|
||||
|
||||
set((state) => {
|
||||
state.tradeHistory = [...state.tradeHistory, ...perpHistory]
|
||||
})
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error('Error fetching trade history', e)
|
||||
})
|
||||
|
||||
if (selectedMangoAccount.spotOpenOrdersAccounts.length) {
|
||||
const openOrdersAccounts =
|
||||
selectedMangoAccount.spotOpenOrdersAccounts.filter(isDefined)
|
||||
const publicKeys = openOrdersAccounts.map((act) =>
|
||||
act.publicKey.toString()
|
||||
)
|
||||
serumTradeHistory = await Promise.all(
|
||||
Promise.all(
|
||||
publicKeys.map(async (pk) => {
|
||||
const response = await fetch(
|
||||
`https://event-history-api.herokuapp.com/trades/open_orders/${pk.toString()}`
|
||||
|
@ -538,16 +552,18 @@ const useMangoStore = create<MangoStore>((set, get) => {
|
|||
return parsedResponse?.data ? parsedResponse.data : []
|
||||
})
|
||||
)
|
||||
.then((serumTradeHistory) => {
|
||||
set((state) => {
|
||||
state.tradeHistory = [
|
||||
...serumTradeHistory,
|
||||
...state.tradeHistory,
|
||||
]
|
||||
})
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error('Error fetching trade history', e)
|
||||
})
|
||||
}
|
||||
const perpHistory = await fetch(
|
||||
`https://event-history-api.herokuapp.com/perp_trades/${selectedMangoAccount.publicKey.toString()}`
|
||||
)
|
||||
let parsedPerpHistory = await perpHistory.json()
|
||||
parsedPerpHistory = parsedPerpHistory?.data || []
|
||||
|
||||
set((state) => {
|
||||
state.tradeHistory = [...serumTradeHistory, ...parsedPerpHistory]
|
||||
})
|
||||
},
|
||||
async reloadMangoAccount() {
|
||||
const set = get().set
|
||||
|
|
34
yarn.lock
34
yarn.lock
|
@ -3123,6 +3123,11 @@ base-x@^3.0.2:
|
|||
dependencies:
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
base64-arraybuffer@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz#1c37589a7c4b0746e34bd1feb951da2df01c1bdc"
|
||||
integrity sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==
|
||||
|
||||
base64-js@^1.0.2, base64-js@^1.3.1, base64-js@^1.5.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
||||
|
@ -3898,6 +3903,13 @@ css-has-pseudo@^3.0.2:
|
|||
dependencies:
|
||||
postcss-selector-parser "^6.0.8"
|
||||
|
||||
css-line-break@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/css-line-break/-/css-line-break-2.1.0.tgz#bfef660dfa6f5397ea54116bb3cb4873edbc4fa0"
|
||||
integrity sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==
|
||||
dependencies:
|
||||
utrie "^1.0.2"
|
||||
|
||||
css-prefers-color-scheme@^6.0.2:
|
||||
version "6.0.2"
|
||||
resolved "https://registry.yarnpkg.com/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.2.tgz#d5c03a980caab92d8beeee176a8795d331e0c727"
|
||||
|
@ -5257,6 +5269,14 @@ html-tags@^3.1.0:
|
|||
resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140"
|
||||
integrity sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==
|
||||
|
||||
html2canvas@^1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/html2canvas/-/html2canvas-1.4.1.tgz#7cef1888311b5011d507794a066041b14669a543"
|
||||
integrity sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==
|
||||
dependencies:
|
||||
css-line-break "^2.1.0"
|
||||
text-segmentation "^1.0.3"
|
||||
|
||||
http-errors@1.7.3:
|
||||
version "1.7.3"
|
||||
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06"
|
||||
|
@ -9168,6 +9188,13 @@ text-encoding-utf-8@^1.0.2:
|
|||
resolved "https://registry.yarnpkg.com/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz#585b62197b0ae437e3c7b5d0af27ac1021e10d13"
|
||||
integrity sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==
|
||||
|
||||
text-segmentation@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/text-segmentation/-/text-segmentation-1.0.3.tgz#52a388159efffe746b24a63ba311b6ac9f2d7943"
|
||||
integrity sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==
|
||||
dependencies:
|
||||
utrie "^1.0.2"
|
||||
|
||||
text-table@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
|
||||
|
@ -9505,6 +9532,13 @@ util@0.12.4, util@^0.12.0:
|
|||
safe-buffer "^5.1.2"
|
||||
which-typed-array "^1.1.2"
|
||||
|
||||
utrie@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/utrie/-/utrie-1.0.2.tgz#d42fe44de9bc0119c25de7f564a6ed1b2c87a645"
|
||||
integrity sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==
|
||||
dependencies:
|
||||
base64-arraybuffer "^1.0.2"
|
||||
|
||||
uuid@^8.3.0, uuid@^8.3.2:
|
||||
version "8.3.2"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
|
||||
|
|
Loading…
Reference in New Issue