diff --git a/app/src/components/common/form/textfield_custom_symbol/index.tsx b/app/src/components/common/form/textfield_custom_symbol/index.tsx
index 1edf6f6418..e3e63363be 100644
--- a/app/src/components/common/form/textfield_custom_symbol/index.tsx
+++ b/app/src/components/common/form/textfield_custom_symbol/index.tsx
@@ -5,6 +5,7 @@ import { CommonDisabledCSS } from '../common_styled'
interface Props {
disabled?: boolean
+ error?: boolean
formField: any
symbol: any
shouldDisplayMaxButton?: boolean
@@ -12,10 +13,10 @@ interface Props {
style?: CSSProperties | undefined
}
-const FieldWrapper = styled.div`
+const FieldWrapper = styled.div<{ error?: boolean }>`
align-items: center;
background-color: ${props => props.theme.textfield.backgroundColor};
- border-color: ${props => props.theme.textfield.borderColor};
+ border-color: ${props => (props.error ? props.theme.alert : props.theme.border1)};
border-style: ${props => props.theme.textfield.borderStyle};
border-width: ${props => props.theme.textfield.borderWidth};
border-radius: ${props => props.theme.textfield.borderRadius};
@@ -26,16 +27,16 @@ const FieldWrapper = styled.div`
width: 100%;
&:hover {
- border-color: ${props => props.theme.textfield.borderColorOnHover};
+ border-color: ${props => (props.error ? props.theme.alert : props.theme.border2)};
.btn--max {
- border-color: ${props => props.theme.textfield.borderColorOnHover};
+ border-color: ${props => (props.error ? props.theme.alert : props.theme.border2)};
}
}
&:focus-within {
- border-color: ${props => props.theme.textfield.borderColorActive};
+ border-color: ${props => (props.error ? props.theme.alert : props.theme.border3)};
.btn--max {
- border-color: ${props => props.theme.textfield.borderColorActive};
+ border-color: ${props => (props.error ? props.theme.alert : props.theme.border3)};
}
}
@@ -44,12 +45,12 @@ const FieldWrapper = styled.div`
> input {
background-color: transparent;
border: none;
- color: ${props => props.theme.textfield.color};
+ color: ${props => props.theme.text2};
flex-grow: 1;
font-family: ${props => props.theme.fonts.fontFamily};
font-size: ${props => props.theme.textfield.fontSize};
- font-weight: ${props => props.theme.textfield.fontWeight};
- line-height: 1.2;
+ font-weight: 400;
+ line-height: 18px;
margin: 0 5px 0 0;
min-width: 0;
outline: ${props => props.theme.textfield.outline};
@@ -91,7 +92,7 @@ const FieldWrapper = styled.div`
`
const Symbol = styled.span<{ marginRight?: boolean }>`
- color: ${props => props.theme.colors.primary};
+ color: ${props => props.theme.text2};
flex-shrink: 0;
font-size: 14px;
font-weight: 500;
@@ -124,7 +125,6 @@ const MaxButton = styled.span`
export const TextfieldCustomSymbol = (props: Props) => {
const { disabled, formField, onClickMaxButton, shouldDisplayMaxButton, symbol, ...restProps } = props
-
// eslint-disable-next-line no-warning-comments
//TODO: use a input[text] instead of passing a
return (
diff --git a/app/src/components/market/common_sections/message_text/warning_message/index.tsx b/app/src/components/market/common_sections/message_text/warning_message/index.tsx
index 0b9a0c0179..d4837d204c 100644
--- a/app/src/components/market/common_sections/message_text/warning_message/index.tsx
+++ b/app/src/components/market/common_sections/message_text/warning_message/index.tsx
@@ -32,7 +32,7 @@ const Description = styled.p`
width: 100%;
&.danger {
- color: ${props => props.theme.message.colors.error};
+ color: ${props => props.theme.alert};
}
`
diff --git a/app/src/components/market/common_styled/index.tsx b/app/src/components/market/common_styled/index.tsx
index 64935c9236..2a39d17031 100644
--- a/app/src/components/market/common_styled/index.tsx
+++ b/app/src/components/market/common_styled/index.tsx
@@ -168,7 +168,7 @@ export const ErrorsWrapper = styled.div`
`
export const GenericError = styled.p<{ margin?: string }>`
- color: ${props => props.theme.colors.error};
+ color: ${props => props.theme.alert};
font-size: 13px;
font-weight: 500;
line-height: 1.5;
diff --git a/app/src/components/market/market_buy/market_buy.tsx b/app/src/components/market/market_buy/market_buy.tsx
index 05da44ea5a..591adb5d67 100644
--- a/app/src/components/market/market_buy/market_buy.tsx
+++ b/app/src/components/market/market_buy/market_buy.tsx
@@ -205,6 +205,7 @@ const MarketBuyWrapper: React.FC = (props: Props) => {
{
= (props: Props) => {
const { proxyIsUpToDate, updateProxy } = useCpkProxy(collateral.address === pseudoNativeAssetAddress)
const isUpdated = RemoteData.hasData(proxyIsUpToDate) ? proxyIsUpToDate.data : true
+ const { relayFeeGreaterThanAmount, relayFeeGreaterThanBalance } = useRelay(amount || new BigNumber(0), collateral)
+
useEffect(() => {
dispatch(fetchAccountBalance(account, provider, collateral))
}, [dispatch, account, provider, collateral])
@@ -285,10 +287,14 @@ const FundingAndFeeStep: React.FC = (props: Props) => {
? null
: !maybeCollateralBalance.eq(collateralBalance)
? null
+ : relayFeeGreaterThanBalance
+ ? 'Insufficient Dai in your Omen Account'
: maybeCollateralBalance.isZero() && funding.gt(maybeCollateralBalance)
? `Insufficient balance`
: funding.gt(maybeCollateralBalance)
? `Value must be less than or equal to ${collateralBalanceFormatted} ${collateral.symbol}`
+ : relayFeeGreaterThanAmount
+ ? 'Relay fee is greater than buy amount'
: null
const isCreateMarketbuttonDisabled =
@@ -472,6 +478,7 @@ const FundingAndFeeStep: React.FC = (props: Props) => {
/>
= (props: Props) => {
= (props: Props) => {
{
{
{
shouldDisplayMaxButton
symbol="Shares"
/>
-
{sharesAmountError && {sharesAmountError}}
>
)}
diff --git a/app/src/components/market/market_sell/market_sell.tsx b/app/src/components/market/market_sell/market_sell.tsx
index 0739551f74..caffa5651a 100644
--- a/app/src/components/market/market_sell/market_sell.tsx
+++ b/app/src/components/market/market_sell/market_sell.tsx
@@ -98,6 +98,7 @@ const MarketSellWrapper: React.FC = (props: Props) => {
{
/>
{
+ const { account, balances, networkId, relay } = useConnectedWeb3Context()
+
+ const [relayAddress, setRelayAddress] = useState('')
+ const [relayFee, setRelayFee] = useState(new BigNumber('0'))
+ const [relayFeeGreaterThanAmount, setRelayFeeGreaterThanAmount] = useState(false)
+ const [relayFeeGreaterThanBalance, setRelayFeeGreaterThanBalance] = useState(false)
+
+ const fetchRelayInfo = async (status?: Status) => {
+ const relayService = new RelayService()
+ const { address, fee } = await relayService.getInfo()
+ if (!status || status.active) {
+ setRelayAddress(address)
+
+ const feeBN = new BigNumber(fee)
+ setRelayFee(feeBN)
+ setRelayFeeGreaterThanBalance(feeBN.gt(balances.xDaiBalance))
+ }
+ }
+
+ useEffect(() => {
+ const status = { active: true }
+ if (account && relay) {
+ fetchRelayInfo(status)
+ } else {
+ setRelayAddress('')
+ setRelayFee(new BigNumber('0'))
+ setRelayFeeGreaterThanBalance(false)
+ }
+ return () => {
+ status.active = false
+ }
+ // eslint-disable-next-line
+ }, [account, networkId, relay])
+
+ useEffect(() => {
+ if (account && relay && collateral && amount) {
+ const native = getNativeAsset(networkId, relay)
+ const feeGreaterThanAmount =
+ relay && amount && !amount.isZero() && relayFee.gt(amount) && collateral.address === native.address
+ setRelayFeeGreaterThanAmount(feeGreaterThanAmount)
+ } else {
+ setRelayFeeGreaterThanAmount(false)
+ }
+ }, [amount, collateral, account, relay, networkId, relayFee])
+
+ return { relayAddress, relayFee, relayFeeGreaterThanAmount, relayFeeGreaterThanBalance }
+}
diff --git a/app/src/pages/market_sections/market_buy_container.tsx b/app/src/pages/market_sections/market_buy_container.tsx
index e21c5254cc..cc8a99c91d 100644
--- a/app/src/pages/market_sections/market_buy_container.tsx
+++ b/app/src/pages/market_sections/market_buy_container.tsx
@@ -6,7 +6,14 @@ import { STANDARD_DECIMALS } from '../../common/constants'
import { MarketBuy } from '../../components/market/market_buy/market_buy'
import { ScalarMarketBuy } from '../../components/market/market_buy/scalar_market_buy'
import { ConnectedWeb3Context, useConnectedWeb3Context } from '../../contexts'
-import { useAsyncDerivedValue, useCollateralBalance, useContracts, useCpkAllowance, useCpkProxy } from '../../hooks'
+import {
+ useAsyncDerivedValue,
+ useCollateralBalance,
+ useContracts,
+ useCpkAllowance,
+ useCpkProxy,
+ useRelay,
+} from '../../hooks'
import { CPKService, MarketMakerService } from '../../services'
import { getNativeAsset, pseudoNativeAssetAddress } from '../../util/networks'
import { RemoteData } from '../../util/remote_data'
@@ -118,6 +125,8 @@ const MarketBuyContainer: React.FC = (props: Props) => {
context,
)
+ const { relayFeeGreaterThanAmount, relayFeeGreaterThanBalance } = useRelay(amount, collateral)
+
useEffect(() => {
setIsNegativeAmount((amount || Zero).lt(Zero))
}, [amount, collateral.decimals])
@@ -201,10 +210,14 @@ const MarketBuyContainer: React.FC = (props: Props) => {
? null
: maybeCollateralBalance === null
? null
+ : relayFeeGreaterThanBalance
+ ? 'Insufficient Dai in your Omen Account'
: maybeCollateralBalance.isZero() && amount?.gt(maybeCollateralBalance)
? `Insufficient balance`
: amount?.gt(maybeCollateralBalance)
? `Value must be less than or equal to ${currentBalance} ${collateral.symbol}`
+ : relayFeeGreaterThanAmount
+ ? 'Relay fee is greater than buy amount'
: null
const unlockCollateral = async () => {
@@ -245,7 +258,9 @@ const MarketBuyContainer: React.FC = (props: Props) => {
hasEnoughAllowance !== Ternary.True) ||
amountError !== null ||
isNegativeAmount ||
- !isUpdated
+ !isUpdated ||
+ relayFeeGreaterThanAmount ||
+ relayFeeGreaterThanBalance
const shouldDisplayMaxButton = collateral.address !== pseudoNativeAssetAddress
const sharesTotal = bigNumberToString(tradedShares, collateral.decimals)
diff --git a/app/src/pages/market_sections/market_pool_liquidity_container.tsx b/app/src/pages/market_sections/market_pool_liquidity_container.tsx
index 86e7c51ab8..d86ef91bfe 100644
--- a/app/src/pages/market_sections/market_pool_liquidity_container.tsx
+++ b/app/src/pages/market_sections/market_pool_liquidity_container.tsx
@@ -13,6 +13,7 @@ import {
useCpkProxy,
useFundingBalance,
useGraphLiquidityMiningCampaigns,
+ useRelay,
} from '../../hooks'
import { GraphResponseLiquidityMiningCampaign } from '../../hooks/useGraphLiquidityMiningCampaigns'
import { useTokenPrice } from '../../hooks/useTokenPrice'
@@ -179,6 +180,11 @@ const MarketPoolLiquidityContainer: React.FC = (props: Props) => {
const totalUserLiquidity = totalDepositedTokens.add(userEarnings).add(userStakedTokens)
+ const { relayFeeGreaterThanAmount, relayFeeGreaterThanBalance } = useRelay(
+ amountToFund || new BigNumber(0),
+ collateral,
+ )
+
const { proxyIsUpToDate, updateProxy } = useCpkProxy()
const isUpdated = RemoteData.hasData(proxyIsUpToDate) ? proxyIsUpToDate.data : true
@@ -186,16 +192,22 @@ const MarketPoolLiquidityContainer: React.FC = (props: Props) => {
? null
: maybeCollateralBalance === null
? null
+ : relayFeeGreaterThanBalance
+ ? 'Insufficient Dai in your Omen Account'
: maybeCollateralBalance.isZero() && amountToFund?.gt(maybeCollateralBalance)
? `Insufficient balance`
: amountToFund?.gt(maybeCollateralBalance)
? `Value must be less than or equal to ${walletBalance} ${collateral.symbol}`
+ : relayFeeGreaterThanAmount
+ ? 'Relay fee is greater than buy amount'
: null
const sharesAmountError = isTransactionProcessing
? null
: maybeFundingBalance === null
? null
+ : relayFeeGreaterThanBalance
+ ? 'Insufficient Dai in your Omen Account'
: maybeFundingBalance.isZero() && amountToRemove?.gt(maybeFundingBalance) && amountToRemove?.gt(userStakedTokens)
? `Insufficient balance`
: amountToRemove?.gt(fundingBalance) && amountToRemove?.gt(userStakedTokens)
@@ -215,7 +227,8 @@ const MarketPoolLiquidityContainer: React.FC = (props: Props) => {
(!cpk?.isSafeApp && collateral.address !== pseudoNativeAssetAddress && hasEnoughAllowance !== Ternary.True) ||
collateralAmountError !== null ||
currentDate > resolutionDate ||
- isNegativeAmountToFund
+ isNegativeAmountToFund ||
+ relayFeeGreaterThanAmount
const upgradeProxy = async () => {
if (!cpk) {
diff --git a/app/src/pages/market_sections/market_sell_container.tsx b/app/src/pages/market_sections/market_sell_container.tsx
index 608f4bfdca..cb6a61139f 100644
--- a/app/src/pages/market_sections/market_sell_container.tsx
+++ b/app/src/pages/market_sections/market_sell_container.tsx
@@ -6,7 +6,7 @@ import { STANDARD_DECIMALS } from '../../common/constants'
import { MarketSell } from '../../components/market/market_sell/market_sell'
import { ScalarMarketSell } from '../../components/market/market_sell/scalar_market_sell'
import { useConnectedWeb3Context } from '../../contexts'
-import { useAsyncDerivedValue, useContracts } from '../../hooks'
+import { useAsyncDerivedValue, useContracts, useRelay } from '../../hooks'
import { MarketMakerService } from '../../services'
import { getLogger } from '../../util/logger'
import {
@@ -81,6 +81,8 @@ const MarketSellContainer: React.FC = (props: Props) => {
const [amountSharesToDisplay, setAmountSharesToDisplay] = useState('')
const [message, setMessage] = useState('')
+ const { relayFeeGreaterThanBalance } = useRelay()
+
let defaultOutcomeIndex = 0
for (let i = 0; i < balances.length; i++) {
const shares = bigNumberToNumber(balances[i].shares, collateral.decimals)
@@ -122,6 +124,8 @@ const MarketSellContainer: React.FC = (props: Props) => {
? null
: balanceItem.shares === null
? null
+ : relayFeeGreaterThanBalance
+ ? 'Insufficient Dai in your Omen Account'
: balanceItem.shares.isZero() && amountShares?.gt(balanceItem.shares)
? `Insufficient balance`
: amountShares?.gt(balanceItem.shares)
diff --git a/app/src/services/cpk/fns.ts b/app/src/services/cpk/fns.ts
index 7d9e58c81b..7905bf2ba4 100644
--- a/app/src/services/cpk/fns.ts
+++ b/app/src/services/cpk/fns.ts
@@ -105,14 +105,22 @@ export const exec = async (params: ExecParams) => {
*/
interface FeeParams {
- service: CPKService
amount: BigNumber
+ collateral: Token
+ service: CPKService
+ native: Token
}
export const fee = async (params: FeeParams) => {
- const { service } = params
- const amount = await service.subRelayFee(params.amount)
- return { ...params, amount }
+ const { collateral, native, service } = params
+ if (service.cpk.relay && collateral.address === native.address) {
+ const amount = await service.subRelayFee(params.amount)
+ if (amount.lte(0)) {
+ throw new Error('Purchase amount is too small')
+ }
+ return { ...params, amount }
+ }
+ return params
}
/**
diff --git a/app/src/services/index.tsx b/app/src/services/index.tsx
index 8495d5810f..2583e14245 100644
--- a/app/src/services/index.tsx
+++ b/app/src/services/index.tsx
@@ -11,3 +11,4 @@ export { OvmService } from './ovm'
export { XdaiService } from './xdai'
export { AirdropService } from './airdrop'
export { OmenGuildService } from './guild'
+export { RelayService } from './relay'