Skip to content

Commit

Permalink
Merge pull request #265 from lidofinance/refactor/stonks
Browse files Browse the repository at this point in the history
Stonks Improvements
  • Loading branch information
AnnaSila authored May 28, 2024
2 parents 0bdc468 + 5526d56 commit d7c08c9
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 51 deletions.
5 changes: 4 additions & 1 deletion modules/stonks/hooks/useOrderData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { connectContractRpc } from 'modules/motions/utils/connectContractRpc'
import { connectERC20Contract } from 'modules/motions/utils/connectTokenContract'
import { useSWR } from 'modules/network/hooks/useSwr'
import moment from 'moment'
import { OrderDetailed, OrderStatus } from '../types'
import { OrderDetailed, OrderStatus, OrderTransaction } from '../types'
import { fetchOffChainOrder } from '../utils/fetchOffChainOrder'
import { formatValue } from '../utils/formatValue'

Expand Down Expand Up @@ -66,6 +66,7 @@ export function useOrderData(orderAddress: string) {
let executedBuyAmount = '0'
let sellAmountFulfillment = '0'
let buyAmountFulfillment = '0'
let transactions: OrderTransaction[] = []

if (offChainOrder) {
executedSellAmount = formatValue(
Expand All @@ -88,6 +89,7 @@ export function useOrderData(orderAddress: string) {

status = offChainOrder.status
isCreatable = false
transactions = offChainOrder.transactions
}

return {
Expand All @@ -113,6 +115,7 @@ export function useOrderData(orderAddress: string) {
creationDate: offChainOrder?.creationDate,
sellAmountWei,
buyAmountWei,
transactions,
}
},
{
Expand Down
6 changes: 6 additions & 0 deletions modules/stonks/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ type OffChainOrderStatus =

export type OrderStatus = 'not-created' | OffChainOrderStatus

export type OrderTransaction = {
txHash: string
}

export type OffChainOrder = {
creationDate: string
owner: string
Expand All @@ -39,6 +43,7 @@ export type OffChainOrder = {
executedBuyAmount: string
receiver: string
status: OffChainOrderStatus
transactions: OrderTransaction[]
}

export type OrderDetailed = {
Expand Down Expand Up @@ -66,6 +71,7 @@ export type OrderDetailed = {
executedBuyAmount?: string
sellAmountFulfillment?: string
buyAmountFulfillment?: string
transactions?: OrderTransaction[]
}

export type StonksData = {
Expand Down
98 changes: 70 additions & 28 deletions modules/stonks/ui/StonksOrderCard/StonksOrderCard.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { ButtonIcon, trimAddress, Copy } from '@lidofinance/lido-ui'
import { useCopyToClipboard } from 'modules/shared/hooks/useCopyToClipboard'
import { getEtherscanLink } from '@lido-sdk/helpers'
import { trimAddress } from '@lidofinance/lido-ui'
import { useWeb3 } from 'modules/blockChain/hooks/useWeb3'
import { AddressInlineWithPop } from 'modules/shared/ui/Common/AddressInlineWithPop'
import { AddressWithPop } from 'modules/shared/ui/Common/AddressWithPop'
import { Text } from 'modules/shared/ui/Common/Text'
import { FormattedDate } from 'modules/shared/ui/Utils/FormattedDate'
import { OrderDetailed } from 'modules/stonks/types'
import { getOffChainOrderUrl } from 'modules/stonks/utils/getOffChainOrderUrl'
import { getOrderStatusText } from 'modules/stonks/utils/getOrderStatusText'
import moment from 'moment'
import { StonksOrderCardCreateButton } from './StonksOrderCardCreateButton'
Expand All @@ -15,6 +18,8 @@ import {
StatusLabel,
StatusValue,
ButtonsRow,
OrderUid,
Link,
} from './StonksOrderCardStyle'

type Props = {
Expand All @@ -28,44 +33,42 @@ export function StonksOrderCard({
isDataValidating,
onInvalidate,
}: Props) {
const handleCopyUid = useCopyToClipboard(order.uid ?? '')
const { chainId } = useWeb3()

const orderLink = getOffChainOrderUrl(order.uid, chainId)
return (
<Card>
<OrderTitle>
<div>
Stonks Order <AddressInlineWithPop address={order.address} />
<OrderUid>
Stonks order <AddressInlineWithPop address={order.address} />
</OrderUid>
<Text size={14} weight={800}>
{order.sellTokenLabel}{order.buyTokenLabel}
</Text>
</div>

<div>
<StatusLabel>Status</StatusLabel>
<StatusValue
isActive={order.status === 'open'}
isCancelled={
order.status === 'cancelled' || order.status === 'expired'
}
>
<StatusValue value={order.status}>
{getOrderStatusText(order.status)}
</StatusValue>
</div>
</OrderTitle>
{order.uid ? (
<Row>
<div>Off-Chain UID</div>
<div>
{trimAddress(order.uid, 6)}
<ButtonIcon
onClick={handleCopyUid}
icon={<Copy />}
size="xs"
variant="translucent"
children="Copy"
/>
</div>
<div>Off-Chain Order</div>
{orderLink ? (
<Link href={orderLink} target="_blank" rel="noreferrer">
{trimAddress(order.uid, 6)}
</Link>
) : (
<div>{trimAddress(order.uid, 6)}</div>
)}
</Row>
) : null}
<Row>
<div>Stonks</div>
<div>Stonks Contract</div>
<AddressWithPop address={order.stonks} />
</Row>
<Row>
Expand Down Expand Up @@ -103,12 +106,51 @@ export function StonksOrderCard({
{order.buyAmountFulfillment}%)
</div>
</Row>
<Row>
<div>Recoverable amount</div>
<div>
{order.recoverableAmount} {order.sellTokenLabel}
</div>
</Row>

{order.transactions?.length ? (
<>
{order.transactions.length > 1 ? (
<>
<Row>
<div>Swap transactions:</div>
</Row>
{order.transactions.map(tx => (
<Link
key={tx.txHash}
href={getEtherscanLink(chainId, tx.txHash, 'tx')}
target="_blank"
rel="noreferrer"
>
{trimAddress(tx.txHash, 12)}
</Link>
))}
</>
) : (
<Row>
<div>Swap transaction hash</div>{' '}
<Link
href={getEtherscanLink(
chainId,
order.transactions[0].txHash,
'tx',
)}
target="_blank"
rel="noreferrer"
>
{trimAddress(order.transactions[0].txHash, 6)}
</Link>
</Row>
)}
</>
) : null}
{order.isRecoverable && (
<Row>
<div>Recoverable amount</div>
<div>
{order.recoverableAmount} {order.sellTokenLabel}
</div>
</Row>
)}
{order.isCreatable || order.isRecoverable ? (
<ButtonsRow>
{order.isCreatable && (
Expand Down
53 changes: 36 additions & 17 deletions modules/stonks/ui/StonksOrderCard/StonksOrderCardStyle.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Container, Theme } from '@lidofinance/lido-ui'
import { BREAKPOINT_MOBILE } from 'modules/globalStyles'
import { Text } from 'modules/shared/ui/Common/Text'
import { OrderStatus } from 'modules/stonks/types'
import styled, { css } from 'styled-components'

export const ContentContainer = styled(Container).attrs({
Expand Down Expand Up @@ -34,16 +35,20 @@ export const Card = styled.div`
}
`

export const OrderTitle = styled(Text).attrs({
size: 16,
weight: 800,
})`
export const OrderTitle = styled.div`
margin-bottom: 20px;
display: flex;
align-items: center;
justify-content: space-between;
`

export const OrderUid = styled(Text).attrs({
size: 14,
weight: 800,
})`
color: rgba(39, 56, 82, 0.6);
`

export const StatusLabel = styled(Text).attrs({
size: 12,
weight: 500,
Expand All @@ -53,27 +58,34 @@ export const StatusLabel = styled(Text).attrs({
`

type StatusValueProps = {
isActive: boolean
isCancelled: boolean
value: OrderStatus
}

export const StatusValue = styled(Text).attrs({
size: 14,
weight: 800,
})`
text-transform: uppercase;
letter-spacing: 0.4px;
${({ isActive, theme }: StatusValueProps & { theme: Theme }) =>
isActive &&
css`
color: ${theme.colors.primary};
`}
${({ isCancelled }: StatusValueProps) =>
isCancelled &&
css`
color: #de186b;
`}
${({ value, theme }: StatusValueProps & { theme: Theme }) => {
switch (value) {
case 'fulfilled':
return css`
color: #53ba95;
`
case 'cancelled':
case 'expired':
return css`
color: #de186b;
`
// rgb(0, 163, 255) - link
default:
return css`
color: ${theme.colors.primary};
`
}
}}
`

export const Row = styled(Text).attrs({
Expand All @@ -83,6 +95,7 @@ export const Row = styled(Text).attrs({
display: flex;
justify-content: space-between;
align-items: center;
min-height: 32px;
& > div {
display: flex;
Expand Down Expand Up @@ -116,3 +129,9 @@ export const MessageBox = styled.div`
background-color: rgba(255, 255, 255, 0.4);
border-radius: ${({ theme }) => theme.borderRadiusesMap.md + 'px'};
`

export const Link = styled.a`
color: ${({ theme }) => theme.colors.primary};
text-decoration: none;
font-weight: 600;
`
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ export function StonksOrderResolverForm() {

const handleSubmit = async (values: FormData) => {
try {
const isAddress = utils.isAddress(values.txHashOrAddress)
if (isAddress) {
if (utils.isAddress(values.txHashOrAddress)) {
const orderContract = connectContractRpc(
StonksOrderAbi__factory,
values.txHashOrAddress,
Expand Down
32 changes: 29 additions & 3 deletions modules/stonks/utils/fetchOffChainOrder.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,38 @@
import { CHAINS } from '@lido-sdk/constants'
import { fetcherStandard } from 'modules/network/utils/fetcherStandard'
import { OffChainOrder } from '../types'
import { OffChainOrder, OrderTransaction } from '../types'

const COWSWAP_API_ENDPOINTS: Partial<Record<CHAINS, string | undefined>> = {
[CHAINS.Mainnet]: 'https://api.cow.fi/mainnet/api/v1',
[CHAINS.Goerli]: 'https://api.cow.fi/goerli/api/v1',
}

const fetchOrderTransactions = async (orderUid: string, chainId: CHAINS) => {
try {
const cowApiEndpoint = COWSWAP_API_ENDPOINTS[chainId]

if (!cowApiEndpoint) {
throw new Error(`NO_CHAIN_${chainId}`)
}

const orderTransactions = await fetcherStandard<
OrderTransaction[] | undefined
>(`${cowApiEndpoint}/trades?orderUid=${orderUid}`)

if (!orderTransactions?.length) {
return []
}

return orderTransactions
} catch (error) {
return []
}
}

export const fetchOffChainOrder = async (
orderAddress: string,
chainId: CHAINS,
) => {
): Promise<OffChainOrder | null> => {
try {
const cowApiEndpoint = COWSWAP_API_ENDPOINTS[chainId]

Expand All @@ -26,7 +48,11 @@ export const fetchOffChainOrder = async (
return null
}

return ordersByOwner[0]
const order = ordersByOwner[0]

const transactions = await fetchOrderTransactions(order.uid, chainId)

return { ...order, transactions }
} catch (error) {
return null
}
Expand Down
11 changes: 11 additions & 0 deletions modules/stonks/utils/getOffChainOrderUrl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { CHAINS } from '@lido-sdk/constants'

export const getOffChainOrderUrl = (
orderUid: string | undefined,
chainId: CHAINS,
) => {
if (!orderUid || chainId !== CHAINS.Mainnet) {
return null
}
return `https://explorer.cow.fi/orders/${orderUid}`
}

0 comments on commit d7c08c9

Please sign in to comment.