Skip to content

Commit c4ee6d7

Browse files
committed
cli: organize commands to list and claim rebates
1 parent bc1a2d3 commit c4ee6d7

File tree

5 files changed

+130
-27
lines changed

5 files changed

+130
-27
lines changed

hardhat.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import '@typechain/hardhat'
2727
const SKIP_LOAD = process.env.SKIP_LOAD === 'true'
2828

2929
if (!SKIP_LOAD) {
30-
;['contracts', 'misc', 'query', 'deployment'].forEach((folder) => {
30+
;['contracts', 'misc', 'query', 'deployment', 'actions'].forEach((folder) => {
3131
const tasksPath = path.join(__dirname, 'tasks', folder)
3232
fs.readdirSync(tasksPath)
3333
.filter((pth) => pth.includes('.ts'))

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
"@typescript-eslint/eslint-plugin": "^4.0.0",
3939
"@typescript-eslint/parser": "^4.0.0",
4040
"@typescript-eslint/typescript-estree": "^4.0.0",
41+
"@urql/core": "^2.1.3",
4142
"axios": "^0.21.1",
4243
"bignumber.js": "^9.0.0",
4344
"chai": "^4.3.4",
@@ -55,13 +56,15 @@
5556
"eslint-plugin-standard": "^4.1.0",
5657
"ethereum-waffle": "^3.3.0",
5758
"ethlint": "^1.2.5",
59+
"graphql-tag": "^2.12.4",
5860
"hardhat": "^2.2.0",
5961
"hardhat-abi-exporter": "^2.2.0",
6062
"hardhat-contract-sizer": "^2.0.3",
6163
"hardhat-gas-reporter": "^1.0.4",
6264
"husky": "^4.3.8",
6365
"inquirer": "^8.0.0",
6466
"ipfs-http-client": "47.0.1",
67+
"isomorphic-fetch": "^3.0.0",
6568
"lint-staged": "^10.5.4",
6669
"minimist": "^1.2.5",
6770
"p-queue": "^6.6.1",

tasks/actions/rebates.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { createClient } from '@urql/core'
2+
import gql from 'graphql-tag'
3+
import fetch from 'isomorphic-fetch'
4+
import { task } from 'hardhat/config'
5+
import { HardhatRuntimeEnvironment } from 'hardhat/types'
6+
7+
const range = (min, max) => [...Array(max - min + 1).keys()].map((i) => i + min)
8+
9+
task('action:claim-rebates', 'Claim rebates')
10+
.addParam('poolRange', 'Pool range to claim in "a,b" format')
11+
.setAction(async ({ poolRange }, hre: HardhatRuntimeEnvironment) => {
12+
// const { contracts } = hre
13+
14+
// Parse input
15+
const [fromEpoch, toEpoch] = poolRange.split(',').map((e) => parseInt(e))
16+
const epochs = range(fromEpoch, toEpoch)
17+
console.log(`Scanning rebate pools (from ${fromEpoch} to ${toEpoch})...`)
18+
19+
// Get allocations
20+
const url = 'https://api.thegraph.com/subgraphs/name/graphprotocol/graph-network-mainnet'
21+
const networkSubgraph = createClient({
22+
url,
23+
fetch,
24+
requestPolicy: 'network-only',
25+
})
26+
const query = gql`
27+
query ($epochs: [Int!]!) {
28+
allocations(first: 1000, where: { closedAtEpoch_in: $epochs, status_not: "Claimed" }) {
29+
id
30+
}
31+
}
32+
`
33+
const res = await networkSubgraph.query(query, { epochs }).toPromise()
34+
const allocationIDs = res.data.allocations.map((allo) => allo.id)
35+
console.log(`Found ${allocationIDs.length} allocations`)
36+
console.log(allocationIDs)
37+
38+
// Claim
39+
// TODO: perform gas estimation
40+
// TODO: add confirmation question
41+
// TODO: batch into multiple calls
42+
// const tx = await contracts.Staking.claimMany(allocationIDs, false)
43+
// console.log(tx.hash)
44+
})

tasks/query/rebates.ts

Lines changed: 48 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { BigNumber } from 'ethers'
2+
import { parseEther } from 'ethers/lib/utils'
13
import Table from 'cli-table'
24
import PQueue from 'p-queue'
35
import { task } from 'hardhat/config'
@@ -6,32 +8,53 @@ import '@nomiclabs/hardhat-ethers'
68

79
import '../gre'
810

9-
task('query:rebates', 'List rebate pools').setAction(async (_, hre: HardhatRuntimeEnvironment) => {
10-
const { contracts } = hre
11-
const { formatEther } = hre.ethers.utils
11+
task('query:rebates', 'List rebate pools')
12+
.addParam('count', 'Number of pools to query')
13+
.setAction(async ({ count }, hre: HardhatRuntimeEnvironment) => {
14+
const { contracts } = hre
15+
const { formatEther } = hre.ethers.utils
1216

13-
const table = new Table({
14-
head: ['Epoch', 'Total Fees', 'Claimed Amount', 'Unclaimed Allocs'],
15-
colWidths: [10, 40, 40, 20],
16-
})
17+
const table = new Table({
18+
head: ['Epoch', 'Fees', 'Claimed', 'Allos', 'Done (%)'],
19+
colWidths: [10, 40, 40, 10, 10],
20+
})
21+
22+
// Get epoch data
23+
const currentEpoch = await contracts.EpochManager.currentEpoch()
1724

18-
// Get epoch data
19-
const currentEpoch = await contracts.EpochManager.currentEpoch()
25+
// Summaries
26+
let totalAllos = 0
27+
let totalUnclaimed = BigNumber.from(0)
2028

21-
// Get rebates
22-
const queue = new PQueue({ concurrency: 4 })
23-
for (let i = 0; i < 5; i++) {
24-
const epoch = currentEpoch.sub(i)
25-
const rebatePool = await contracts.Staking.rebates(epoch)
26-
table.push([
27-
epoch,
28-
formatEther(rebatePool.fees),
29-
formatEther(rebatePool.claimedRewards),
30-
rebatePool.unclaimedAllocationsCount,
31-
])
32-
}
33-
await queue.onIdle()
29+
// Get rebates
30+
const items = []
31+
const queue = new PQueue({ concurrency: 10 })
32+
for (let i = 0; i < count; i++) {
33+
queue.add(async () => {
34+
// Calculations
35+
const epoch = currentEpoch.sub(i).toNumber()
36+
const rebatePool = await contracts.Staking.rebates(epoch)
37+
const shareClaimed = rebatePool.fees.gt(0)
38+
? formatEther(rebatePool.claimedRewards.mul(parseEther('1')).div(rebatePool.fees))
39+
: '1'
40+
// Add to table
41+
items.push([
42+
epoch,
43+
formatEther(rebatePool.fees),
44+
formatEther(rebatePool.claimedRewards),
45+
rebatePool.unclaimedAllocationsCount,
46+
Math.round(parseFloat(shareClaimed) * 100),
47+
])
48+
// Add to summaries
49+
totalAllos += rebatePool.unclaimedAllocationsCount
50+
totalUnclaimed = totalUnclaimed.add(rebatePool.fees.sub(rebatePool.claimedRewards))
51+
})
52+
}
53+
await queue.onIdle()
3454

35-
// Display
36-
console.log(table.toString())
37-
})
55+
// Display
56+
table.push(...items.sort((a, b) => b[0] - a[0]))
57+
console.log(table.toString())
58+
console.log(`> Unclaimed Allos: ${totalAllos}`)
59+
console.log(`> Unclaimed Fees: ${formatEther(totalUnclaimed)}`)
60+
})

yarn.lock

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1218,6 +1218,14 @@
12181218
"@graphql-typed-document-node/core" "^3.1.0"
12191219
wonka "^4.0.14"
12201220

1221+
"@urql/core@^2.1.3":
1222+
version "2.1.3"
1223+
resolved "https://registry.yarnpkg.com/@urql/core/-/core-2.1.3.tgz#fd8514ce28c1f8cf8e99a03b86a3df217c132290"
1224+
integrity sha512-CzrTMhO5SG7qdAaS3B5/g1TPH5k7326GHIyta1owT2vzxX9ev8YytxOE5m73EuacxIfF7qVZFhCzY+rubOlI0w==
1225+
dependencies:
1226+
"@graphql-typed-document-node/core" "^3.1.0"
1227+
wonka "^4.0.14"
1228+
12211229
12221230
version "1.0.1"
12231231
resolved "https://registry.yarnpkg.com/@urql/exchange-execute/-/exchange-execute-1.0.1.tgz#4cda7cbb8130c6c99f035927ca5d4756685f1ab4"
@@ -5518,6 +5526,13 @@ [email protected]:
55185526
resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.11.0.tgz#1deb53a01c46a7eb401d6cb59dec86fa1cccbffd"
55195527
integrity sha512-VmsD5pJqWJnQZMUeRwrDhfgoyqcfwEkvtpANqcoUG8/tOLkwNgU9mzub/Mc78OJMhHjx7gfAMTxzdG43VGg3bA==
55205528

5529+
graphql-tag@^2.12.4:
5530+
version "2.12.4"
5531+
resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.12.4.tgz#d34066688a4f09e72d6f4663c74211e9b4b7c4bf"
5532+
integrity sha512-VV1U4O+9x99EkNpNmCUV5RZwq6MnK4+pGbRYWG+lA/m3uo7TSqJF81OkcOP148gFP6fzdl7JWYBrwWVTS9jXww==
5533+
dependencies:
5534+
tslib "^2.1.0"
5535+
55215536
55225537
version "15.4.0"
55235538
resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.4.0.tgz#e459dea1150da5a106486ba7276518b5295a4347"
@@ -6577,6 +6592,14 @@ isobject@^3.0.0, isobject@^3.0.1:
65776592
resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
65786593
integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=
65796594

6595+
isomorphic-fetch@^3.0.0:
6596+
version "3.0.0"
6597+
resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz#0267b005049046d2421207215d45d6a262b8b8b4"
6598+
integrity sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==
6599+
dependencies:
6600+
node-fetch "^2.6.1"
6601+
whatwg-fetch "^3.4.1"
6602+
65806603
isstream@~0.1.2:
65816604
version "0.1.2"
65826605
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
@@ -8048,7 +8071,7 @@ [email protected]:
80488071
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.1.2.tgz#ab884e8e7e57e38a944753cec706f788d1768bb5"
80498072
integrity sha1-q4hOjn5X44qUR1POxwb3iNF2i7U=
80508073

8051-
[email protected], node-fetch@^2.6.0:
8074+
[email protected], node-fetch@^2.6.0, node-fetch@^2.6.1:
80528075
version "2.6.1"
80538076
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
80548077
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
@@ -10851,6 +10874,11 @@ tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
1085110874
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
1085210875
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
1085310876

10877+
tslib@^2.1.0:
10878+
version "2.3.0"
10879+
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e"
10880+
integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==
10881+
1085410882
1085510883
version "0.0.1"
1085610884
resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786"
@@ -11803,6 +11831,11 @@ [email protected]:
1180311831
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f"
1180411832
integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==
1180511833

11834+
whatwg-fetch@^3.4.1:
11835+
version "3.6.2"
11836+
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c"
11837+
integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==
11838+
1180611839
which-boxed-primitive@^1.0.2:
1180711840
version "1.0.2"
1180811841
resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"

0 commit comments

Comments
 (0)