Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Liq rewards proposals #2205

Draft
wants to merge 25 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
70d2825
feature: start work on liq rewards proposals
hexyls Aug 13, 2021
c5fc39d
feature: add start of market card
hexyls Aug 16, 2021
3ebb014
feature: fetch data, add collateral multicall, use market home contai…
hexyls Aug 17, 2021
9a987ef
Merge branch 'master' into feature/2044
hexyls Aug 17, 2021
36843ae
feat: start work on the guild contract interaction
hexyls Aug 18, 2021
9d17f6c
feat: basic of proposeLiquidityRewards pipe
hexyls Aug 18, 2021
3ab4c6c
style: refine styling
hexyls Aug 19, 2021
5b626da
Merge branch 'master' into feature/2044
hexyls Aug 19, 2021
fb54b59
Merge branch 'master' into feature/2044
Mi-Lan Aug 19, 2021
096effb
Merge branch 'master' into feature/2044
hexyls Aug 20, 2021
a0602bc
fix: grid layout, card styling, pageSize pagination filters, page/vie…
hexyls Aug 20, 2021
490afe6
Merge branch 'feature/2044' of github.com:protofire/omen-exchange int…
hexyls Aug 20, 2021
4bd980d
fix: compress outcome perc when greater than 2 outcomes
hexyls Aug 25, 2021
f860998
fix: add scalar market design
hexyls Aug 27, 2021
d7d8fa6
Merge branch 'master' into feature/2044
Mi-Lan Aug 27, 2021
be4398f
Merge branch 'master' into feature/2044
hexyls Aug 30, 2021
4efe168
feature: start work on full proposal flow
hexyls Aug 30, 2021
c065d58
Merge branch 'feature/2044' of github.com:protofire/omen-exchange int…
hexyls Aug 30, 2021
1c6ff35
Merge branch 'master' into feature/2044
pimato Aug 30, 2021
9335ede
fix: finish rewards proposal creation flow
hexyls Aug 31, 2021
ef75bdb
Merge branch 'master' into feature/2044
hexyls Sep 1, 2021
b785076
Merge branch 'master' into feature/2044
hexyls Sep 1, 2021
b2a6407
feature: start connecting proposals and proposal details
hexyls Sep 1, 2021
1b1fd2b
feature: format more data
hexyls Sep 2, 2021
6311409
feature: add proposal bar chart
hexyls Sep 3, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions app/src/components/common/icons/IconBack.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from 'react'

export const IconBack = () => (
<svg fill="none" height="12" viewBox="0 0 18 12" width="18" xmlns="http://www.w3.org/2000/svg">
<path d="M18 5H3.83L7.41 1.41L6 0L0 6L6 12L7.41 10.59L3.83 7H18V5Z" />
</svg>
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think its necessary to import another Icon here I used on my proposal details pr IconArrowBack with slight modification to support this color https://github.com/protofire/omen-exchange/pull/2208/files#

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cheers dude, copied!

1 change: 1 addition & 0 deletions app/src/components/common/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,4 @@ export { IconFail } from './IconFail'
export { IconInfo } from './IconInfo'
export { IconPokt } from './IconPokt'
export { IconXdai } from './IconXdai'
export { IconBack } from './IconBack'
20 changes: 6 additions & 14 deletions app/src/components/common/layout/header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,6 @@ const HeaderDropdown = styled(Dropdown)`
`

const MarketAndGovernanceNav = styled.div<{ disabled?: boolean }>`
display: none;
background-color: ${props => (props.disabled ? props => props.theme.buttonSecondary.backgroundColor : 'transparent')};
${props => (props.disabled ? 'pointer-events:none;' : '')};
border-radius: 32px;
color: ${props => (!props.disabled ? props.theme.colors.clickable : props.theme.colors.primary)};
Expand Down Expand Up @@ -198,7 +196,6 @@ const HeaderContainer: React.FC = (props: any) => {
const [isDepositWithdrawModalOpen, setDepositWithdrawModalState] = useState(false)
const [isModalLockTokensOpen, setModalLockTokensState] = useState<boolean>(false)
const [depositWithdrawType, setDepositWithdrawType] = useState<ExchangeType>(ExchangeType.deposit)
const [marketPage, setMarketPage] = useState(true)

const hasRouter = props.history !== undefined
const disableConnectButton = isConnectWalletModalOpen
Expand Down Expand Up @@ -265,6 +262,8 @@ const HeaderContainer: React.FC = (props: any) => {
onClick: () => history && history.push('/'),
}

const isMarketPage = history.location.pathname === '/liquidity'
const isGuildPage = history.location.pathname === '/guild'
return (
<HeaderWrapper {...restProps}>
<HeaderInner>
Expand All @@ -273,21 +272,14 @@ const HeaderContainer: React.FC = (props: any) => {
<Logo />
</LogoWrapper>
<MarketAndGovernanceNav
disabled={marketPage}
onClick={() => {
setMarketPage(!marketPage)
}}
disabled={isMarketPage}
onClick={() => history && history.push('/')}
style={{ marginLeft: '48px' }}
>
Markets
</MarketAndGovernanceNav>
<MarketAndGovernanceNav
disabled={!marketPage}
onClick={() => {
setMarketPage(!marketPage)
}}
>
Governance
<MarketAndGovernanceNav disabled={isGuildPage} onClick={() => history && history.push('/guild')}>
Guild
</MarketAndGovernanceNav>
</ContentsLeft>
<ContentsRight>
Expand Down
276 changes: 276 additions & 0 deletions app/src/components/guild/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
import { BigNumber } from 'ethers/utils'
import React, { useEffect, useState } from 'react'
import styled from 'styled-components'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great that you created guild in the components folder I did the same thing on mine! Also In order to keep separation of concerns I think it might make sense to create guild folder inside pages folder and store all the logic there and separate it from view which will be stored in components? Curios what you and Kaden think about this and how we should go about it...You can also checkout maybe how I did it and if it makes sense or if we should do It differently.... @kadenzipfel @hexyls

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like this idea, made a proposed_rewards_page.tsx and a proposed_rewards_view.tsx, much better now

import { ConnectedWeb3Context } from '../../contexts'
import { OmenGuildService } from '../../services/guild'
import { getLogger } from '../../util/logger'
import { RemoteData } from '../../util/remote_data'
import { MarketFilters, MarketMakerDataItem, TransactionStep } from '../../util/types'
import { Button } from '../button'
import { ButtonType } from '../button/button_styling_types'
import { IconBack } from '../common/icons'
import { MarketCard } from '../market/market_card'
import { ModalTransactionWrapper } from '../modal/modal_transaction'

const logger = getLogger('Guild::Propose')

interface Props {
count: number
context: ConnectedWeb3Context
currentFilter: any
isFiltering?: boolean
fetchMyMarkets: boolean
markets: RemoteData<MarketMakerDataItem[]>
moreMarkets: boolean
pageIndex: number
onFilterChange: (filter: MarketFilters) => void
onLoadNextPage: () => void
onLoadPrevPage: () => void
}

const GuildPageWrapper = styled.div`
width: 100%;
@media (max-width: ${props => props.theme.themeBreakPoints.xxl}) {
padding: 0 14px;
}
`

const ProposalHeadingWrapper = styled.div`
display: flex;
justify-content: space-between;
width: 100%;
align-items: center;
@media (max-width: ${props => props.theme.themeBreakPoints.sm}) {
flex-wrap: wrap;
}
`

const ProposalTitle = styled.div`
font-size: 22px;
font-weight: 500;
line-height: 26px;
color: ${props => props.theme.text3};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also for all the text files we should be using new TYPE.something from theme/index.js file It is now on master with recent pr from francesco that we pushed...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done 🏄‍♂️ was cool putting TYPE into action, pretty powerful and easy to use

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right! Its so dope and easy to copy from figma and not have to worry about text style

`

const ProposalSubtitle = styled.div`
font-size: ${props => props.theme.defaultSize};
font-weight: 400;
line-height: 18px;
margin-top: 8px;
color: ${props => props.theme.text2};
`

const ProposalButton = styled(Button)`
@media (max-width: ${props => props.theme.themeBreakPoints.sm}) {
margin-top: 24px;
width: 100%;
}
`

const MarketCardsWrapper = styled.div`
display: flex;
justify-content: space-between;
flex-wrap: wrap;
width: 100%;
margin-top: 12px;
margin-bottom: 32px;
`

const OverviewWrapper = styled.div`
display: flex;
align-items: center;
margin-bottom: 16px;
cursor: pointer;

&:hover svg {
path {
fill: ${props => props.theme.primary1};
}
}

&:hover div {
color: ${props => props.theme.primary1};
}
`

const StyledSvg = styled.svg`
height: 12px;
width: 18px;
path {
fill: ${props => props.theme.primary2};
}
`

const OverviewTitle = styled.div`
font-family: Roboto;
font-style: normal;
font-weight: 500;
font-size: 16px;
line-height: 19px;
display: flex;
align-items: center;
letter-spacing: 0.2px;
margin-left: 16px;
color: ${props => props.theme.primary2};
`

const ButtonWrapper = styled.div`
display: flex;
justify-content: space-between;
`

const ButtonNavWrapper = styled.div`
display: flex;
`

const NextButton = styled(Button)`
margin-left: 12px;
`

const GuildWrapper = (props: Props) => {
const { context, count, isFiltering, markets, moreMarkets, onLoadNextPage, onLoadPrevPage, pageIndex } = props
const { account, balances, cpk, library, networkId, setTxState, txHash, txState } = context

const [propose, setPropose] = useState(false)
const [selected, setSelected] = useState<string[]>([])
const [isTransactionModalOpen, setIsTransactionModalOpen] = useState<boolean>(false)
const [isTransactionProcessing, setIsTransactionProcessing] = useState<boolean>(false)

// eslint-disable-next-line
const [votes, setVotes] = useState(new BigNumber(0))
// eslint-disable-next-line
const [votesRequired, setVotesRequired] = useState(new BigNumber(0))

useEffect(() => {
const getVoteInfo = async () => {
if (!cpk || !account) {
return
}
const omen = new OmenGuildService(library, networkId)
const [votes, required] = await Promise.all([await omen.votesOf(account), await omen.votesForCreation()])
setVotes(votes)
setVotesRequired(required)
}

getVoteInfo()
}, [account, cpk, library, networkId])

const toggle = () => {
setPropose(!propose)
setSelected([])
}

const select = (address: string) => {
if (selected.includes(address)) {
setSelected(selected.filter((addr: string) => addr !== address))
} else {
setSelected([...selected, address])
}
}

const proposeLiquidityRewards = async () => {
try {
if (!cpk) {
return
}

setIsTransactionProcessing(true)
setTxState(TransactionStep.waitingConfirmation)
setIsTransactionModalOpen(true)

// await cpk.proposeLiquidityRewards()
await new Promise(r => setTimeout(r, 3000))

await balances.fetchBalances()
setIsTransactionProcessing(false)
} catch (err) {
logger.error(err.message)
setIsTransactionProcessing(false)
}
}

const proposalButtonDisabled = (propose && !selected.length) || isTransactionProcessing // || votes.isZero() || votes.lt(votesRequired)
const isPrevDisabled = pageIndex === 0
const isNextDisabled = !moreMarkets
return (
<GuildPageWrapper>
{propose && (
<OverviewWrapper onClick={toggle}>
<StyledSvg>
<IconBack />
</StyledSvg>
<OverviewTitle>Guild Overview</OverviewTitle>
</OverviewWrapper>
)}
<ProposalHeadingWrapper>
{propose ? (
<ProposalTitle>Choose Market for liquidity rewards</ProposalTitle>
) : (
<div>
<ProposalTitle>Proposed Liquidity Rewards</ProposalTitle>
<ProposalSubtitle>Reward liquidity providers of popular omen markets with 500 OMN tokens</ProposalSubtitle>
</div>
)}

<ProposalButton
buttonType={ButtonType.primary}
disabled={proposalButtonDisabled}
onClick={propose ? proposeLiquidityRewards : toggle}
>
Propose Liq. Rewards
</ProposalButton>
</ProposalHeadingWrapper>
{propose && (
<MarketCardsWrapper>
{!isFiltering &&
RemoteData.hasData(markets) &&
RemoteData.is.success(markets) &&
markets.data.length > 0 &&
markets.data.slice(0, count).map(item => {
return (
<MarketCard
active={selected.includes(item.address)}
key={item.address}
market={item}
onClick={() => select(item.address)}
/>
)
})}
</MarketCardsWrapper>
)}
{propose && (
<ButtonWrapper>
<Button onClick={toggle}>Back</Button>
<ButtonNavWrapper>
<Button
buttonType={isPrevDisabled ? ButtonType.primary : ButtonType.primaryLine}
disabled={pageIndex === 0}
onClick={onLoadPrevPage}
>
Prev
</Button>
<NextButton
buttonType={isNextDisabled ? ButtonType.primary : ButtonType.primaryLine}
disabled={!moreMarkets}
onClick={onLoadNextPage}
>
Next
</NextButton>
</ButtonNavWrapper>
</ButtonWrapper>
)}
<ModalTransactionWrapper
confirmations={0}
confirmationsRequired={0}
isOpen={isTransactionModalOpen}
message={'Propose Liquidity Rewards'}
onClose={() => setIsTransactionModalOpen(false)}
txHash={txHash}
txState={txState}
/>
</GuildPageWrapper>
)
}

export { GuildWrapper }
2 changes: 1 addition & 1 deletion app/src/components/main/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const Main: React.FC = () => {
<Route component={SettingsViewContainer} exact path="/settings" />
<Route
component={MarketHomeContainer}
path={['/24h-volume', '/volume', '/newest', '/ending', '/liquidity']}
path={['/24h-volume', '/volume', '/newest', '/ending', '/liquidity', '/guild']}
/>
<Route component={MarketWizardCreatorContainer} exact path="/create" />
<Route component={MarketRoutes} path="/:address" />
Expand Down
Loading