Skip to content

Commit 9ba1f69

Browse files
authored
Merge pull request #338 from reflexer-labs/develop
Surplus auctions addons
2 parents 3d22582 + f3b63dd commit 9ba1f69

File tree

3 files changed

+203
-3
lines changed

3 files changed

+203
-3
lines changed

src/containers/Auctions/index.tsx

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ import Modal from '../../components/Modals/Modal'
88
import { useActiveWeb3React } from '../../hooks'
99
import { useStoreActions } from '../../store'
1010
import AuctionsList from './AuctionsList'
11+
import { useStartSurplusAuction } from 'src/hooks/useAuctions'
12+
import { handleTransactionError } from 'src/hooks/TransactionHooks'
13+
import { formatNumber } from 'src/utils/helper'
1114

1215
export type AuctionEventType = 'DEBT' | 'SURPLUS' | 'STAKED_TOKEN'
1316

@@ -22,6 +25,31 @@ const Auctions = ({
2225
const [showFaqs, setShowFaqs] = useState(false)
2326
const [type, setType] = useState<AuctionEventType>('SURPLUS')
2427
const [error, setError] = useState('')
28+
const [isLoading, setIsLoading] = useState(false)
29+
const {
30+
startSurplusAcution,
31+
surplusAmountToSell,
32+
accountingEngineSurplus,
33+
allowStartSurplusAuction,
34+
deltaToStartSurplusAuction,
35+
} = useStartSurplusAuction()
36+
37+
const handleStartSurplusAuction = async () => {
38+
setIsLoading(true)
39+
try {
40+
popupsActions.setIsWaitingModalOpen(true)
41+
popupsActions.setWaitingPayload({
42+
title: 'Waiting For Confirmation',
43+
hint: 'Confirm this transaction in your wallet',
44+
status: 'loading',
45+
})
46+
await startSurplusAcution()
47+
} catch (e) {
48+
handleTransactionError(e)
49+
} finally {
50+
setIsLoading(false)
51+
}
52+
}
2553

2654
useEffect(() => {
2755
async function init() {
@@ -118,6 +146,57 @@ const Auctions = ({
118146
</Tab>
119147
</Switcher>
120148
)}
149+
{type === 'SURPLUS' && account ? (
150+
<StartAuctionContainer>
151+
<Box style={{ justifyContent: 'space-between' }}>
152+
<div>
153+
<Box>
154+
<SurplusTitle>
155+
System Surplus:{' '}
156+
</SurplusTitle>
157+
<span>
158+
{formatNumber(
159+
accountingEngineSurplus as string,
160+
2
161+
)}{' '}
162+
RAI
163+
</span>
164+
</Box>
165+
<Box>
166+
<SurplusTitle>
167+
Surplus Amount to Sell:{' '}
168+
</SurplusTitle>
169+
<span>
170+
{formatNumber(
171+
surplusAmountToSell as string,
172+
2
173+
)}{' '}
174+
RAI
175+
</span>
176+
</Box>
177+
178+
{allowStartSurplusAuction ? null : (
179+
<Box>
180+
(
181+
{formatNumber(
182+
String(deltaToStartSurplusAuction),
183+
2
184+
)}{' '}
185+
RAI) to start an auction
186+
</Box>
187+
)}
188+
</div>
189+
<Button
190+
text={'Start Surplus Auction'}
191+
onClick={handleStartSurplusAuction}
192+
isLoading={isLoading}
193+
disabled={
194+
isLoading || !allowStartSurplusAuction
195+
}
196+
/>
197+
</Box>
198+
</StartAuctionContainer>
199+
) : null}
121200

122201
<AuctionsList type={type} />
123202
</Container>
@@ -187,3 +266,26 @@ const BtnContainer = styled.div`
187266
padding-top: 20px;
188267
text-align: center;
189268
`
269+
270+
const Box = styled.div`
271+
display: flex;
272+
align-items: center;
273+
span {
274+
font-weight: bold;
275+
}
276+
@media (max-width: 767px) {
277+
flex-direction: column;
278+
margin-bottom: 15px;
279+
}
280+
`
281+
const SurplusTitle = styled.h3`
282+
font-size: 16px;
283+
margin-right: 10px;
284+
font-weight: normal;
285+
`
286+
287+
const StartAuctionContainer = styled.div`
288+
padding: 10px 20px;
289+
border-radius: 15px;
290+
background: ${(props) => props.theme.colors.colorSecondary};
291+
`

src/hooks/useAuctions.ts

Lines changed: 100 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
1-
import { useEffect, useState } from 'react'
2-
import { useStoreState } from '../store'
1+
import { useEffect, useMemo, useState } from 'react'
2+
import { useStoreActions, useStoreState } from '../store'
33
import { IAuction } from '../utils/interfaces'
44
import _ from '../utils/lodash'
5+
import { Geb } from 'geb.js'
6+
import { useActiveWeb3React } from '.'
7+
import { ETH_NETWORK } from 'src/utils/constants'
8+
import { handlePreTxGasEstimate } from './TransactionHooks'
9+
import { parseRad } from 'src/utils/gebManager'
10+
import { BigNumber } from 'ethers'
11+
import { toFixedString } from 'src/utils/helper'
512

613
// list auctions data
714
export default function useAuctions() {
@@ -83,3 +90,94 @@ export default function useAuctions() {
8390

8491
return state
8592
}
93+
94+
// start surplus auction
95+
export function useStartSurplusAuction() {
96+
const {
97+
transactionsModel: transactionsActions,
98+
popupsModel: popupsActions,
99+
} = useStoreActions((store) => store)
100+
101+
const { account, library } = useActiveWeb3React()
102+
const [surplusAmountToSell, setSurplusAmountToSell] = useState<string>()
103+
const [accountingEngineSurplus, setAccountingEngineSurplus] =
104+
useState<string>()
105+
106+
useEffect(() => {
107+
if (!library || !account) return
108+
const signer = library.getSigner(account)
109+
const geb = new Geb(ETH_NETWORK, signer.provider)
110+
geb.multiCall([
111+
geb.contracts.accountingEngine.surplusAuctionAmountToSell(true),
112+
geb.contracts.safeEngine.coinBalance(
113+
geb.contracts.accountingEngine.address,
114+
true
115+
),
116+
]).then((res) => {
117+
setSurplusAmountToSell(parseRad(res[0]))
118+
setAccountingEngineSurplus(parseRad(res[1]))
119+
})
120+
}, [account, library])
121+
122+
const allowStartSurplusAuction = useMemo(() => {
123+
if (!surplusAmountToSell || !accountingEngineSurplus) return false
124+
const surplusBuffer = 500_000
125+
const surplusAmountToSellWithBuffer = BigNumber.from(
126+
toFixedString(
127+
String(Number(surplusAmountToSell) + surplusBuffer),
128+
'RAD'
129+
)
130+
)
131+
const accountingEngineSurplusBN = BigNumber.from(
132+
toFixedString(accountingEngineSurplus, 'RAD')
133+
)
134+
return surplusAmountToSellWithBuffer.lte(accountingEngineSurplusBN)
135+
}, [surplusAmountToSell, accountingEngineSurplus])
136+
137+
const deltaToStartSurplusAuction = useMemo(() => {
138+
if (!surplusAmountToSell || !accountingEngineSurplus) return 0
139+
const surplusBuffer = 500_000
140+
const surplusAmountToSellWithBuffer =
141+
Number(surplusAmountToSell) + surplusBuffer
142+
const accountingEngineSurplusN = Number(accountingEngineSurplus)
143+
return surplusAmountToSellWithBuffer - accountingEngineSurplusN
144+
}, [surplusAmountToSell, accountingEngineSurplus])
145+
146+
const startSurplusAcution = async function () {
147+
if (!library || !account) throw new Error('No library or account')
148+
const signer = library.getSigner(account)
149+
const geb = new Geb(ETH_NETWORK, signer.provider)
150+
151+
const txData = geb.contracts.accountingEngine.auctionSurplus()
152+
153+
if (!txData) throw new Error('No transaction request!')
154+
const tx = await handlePreTxGasEstimate(signer, txData)
155+
const txResponse = await signer.sendTransaction(tx)
156+
if (txResponse) {
157+
const { hash, chainId } = txResponse
158+
transactionsActions.addTransaction({
159+
chainId,
160+
hash,
161+
from: txResponse.from,
162+
summary: 'Starting surplus auction',
163+
addedTime: new Date().getTime(),
164+
originalTx: txResponse,
165+
})
166+
popupsActions.setIsWaitingModalOpen(true)
167+
popupsActions.setWaitingPayload({
168+
title: 'Transaction Submitted',
169+
hash: txResponse.hash,
170+
status: 'success',
171+
})
172+
await txResponse.wait()
173+
}
174+
}
175+
176+
return {
177+
startSurplusAcution,
178+
surplusAmountToSell,
179+
accountingEngineSurplus,
180+
allowStartSurplusAuction,
181+
deltaToStartSurplusAuction,
182+
}
183+
}

src/utils/i18n/en.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@
130130
"debt_auction_claim_tokens": "What does the Claim Tokens button do?",
131131
"debt_auction_claim_tokens_desc": "In case someone outbids you in a debt auction, your RAI bid will be reimbursed to your Reflexer Account.Claim Tokens can be used to get back RAI (and FLX) that is kept in your Account.",
132132
"surplus_auction_minting_flx_header": "Selling Surplus RAI",
133-
"surplus_auction_minting_flx_desc": "Surplus auctions are meant to sell RAI that accrued inside the protocol in exchange for FLX. The FLX that is received by an auction will be burned.",
133+
"surplus_auction_minting_flx_desc": "Surplus auctions are meant to sell RAI that accrued inside the protocol in exchange for FLX. The FLX that is received by an auction will be burned. Auction will start when the surplus amount plus 500k (fixed surplus buffer) be less than or equal to System Surplus ",
134134
"surplus_auction_how_to_bid": "How do I bid?",
135135
"surplus_auction_how_to_bid_desc": "During a surplus auction, you will bid an increasing amount of FLX for a fixed amount of RAI. A practical example: if the current FLX bid is 100 for 20K RAI (resulting in a price of 200 RAI/FLX), the next bidder must bid more FLX for the same amount of RAI. The auction also makes sure that each bid must be at least a certain percentage higher than the previous one (e.g the next bid must be at least 3% higher).",
136136
"surplus_auction_claim_tokens": "What does the Claim Tokens button do?",

0 commit comments

Comments
 (0)