@stake-dao/reader 0.5.3 → 0.5.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/abis/lockersMulticall.js +27 -4
- package/dist/esm/abis/lockersMulticall.js.map +1 -1
- package/dist/esm/bytecodes/votemarket/batchYbUserVotes.js +39 -0
- package/dist/esm/bytecodes/votemarket/batchYbUserVotes.js.map +1 -0
- package/dist/esm/bytecodes/votemarket/batchYbVotes.js +13 -0
- package/dist/esm/bytecodes/votemarket/batchYbVotes.js.map +1 -0
- package/dist/esm/index.js +5 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lockers/fetch/parse.js +1 -0
- package/dist/esm/lockers/fetch/parse.js.map +1 -1
- package/dist/esm/lockers/fetch/protocols/balancer.js +3 -0
- package/dist/esm/lockers/fetch/protocols/balancer.js.map +1 -1
- package/dist/esm/lockers/fetch/protocols/pendle.js +11 -1
- package/dist/esm/lockers/fetch/protocols/pendle.js.map +1 -1
- package/dist/esm/prices.js +4 -0
- package/dist/esm/prices.js.map +1 -1
- package/dist/esm/strategies/v2/parse.js +51 -1
- package/dist/esm/strategies/v2/parse.js.map +1 -1
- package/dist/esm/votemarket/fetchClaimableData.js +1 -1
- package/dist/esm/votemarket/fetchEpochVotes.js +13 -4
- package/dist/esm/votemarket/fetchEpochVotes.js.map +1 -1
- package/dist/esm/votemarket/generateProofs/config.js +6 -0
- package/dist/esm/votemarket/generateProofs/config.js.map +1 -1
- package/dist/esm/votemarket/generateProofs/getGaugeProof.js +5 -0
- package/dist/esm/votemarket/generateProofs/getGaugeProof.js.map +1 -1
- package/dist/esm/votemarket/generateProofs/getUserProof.js +13 -2
- package/dist/esm/votemarket/generateProofs/getUserProof.js.map +1 -1
- package/dist/esm/votemarket/yb/fetchYbUserVotes.js +42 -0
- package/dist/esm/votemarket/yb/fetchYbUserVotes.js.map +1 -0
- package/dist/types/abis/lockersMulticall.d.ts.map +1 -1
- package/dist/types/bytecodes/votemarket/batchYbUserVotes.d.ts +4 -0
- package/dist/types/bytecodes/votemarket/batchYbUserVotes.d.ts.map +1 -0
- package/dist/types/bytecodes/votemarket/batchYbVotes.d.ts +4 -0
- package/dist/types/bytecodes/votemarket/batchYbVotes.d.ts.map +1 -0
- package/dist/types/index.d.ts +4 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/lockers/fetch/parse.d.ts +1 -0
- package/dist/types/lockers/fetch/parse.d.ts.map +1 -1
- package/dist/types/lockers/fetch/protocols/balancer.d.ts.map +1 -1
- package/dist/types/lockers/fetch/protocols/pendle.d.ts.map +1 -1
- package/dist/types/prices.d.ts.map +1 -1
- package/dist/types/strategies/v2/parse.d.ts.map +1 -1
- package/dist/types/votemarket/fetchEpochVotes.d.ts.map +1 -1
- package/dist/types/votemarket/generateProofs/config.d.ts +6 -0
- package/dist/types/votemarket/generateProofs/config.d.ts.map +1 -1
- package/dist/types/votemarket/generateProofs/getGaugeProof.d.ts.map +1 -1
- package/dist/types/votemarket/generateProofs/getUserProof.d.ts.map +1 -1
- package/dist/types/votemarket/yb/fetchYbUserVotes.d.ts +16 -0
- package/dist/types/votemarket/yb/fetchYbUserVotes.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/abis/lockersMulticall.ts +27 -4
- package/src/bytecodes/votemarket/batchYbUserVotes.ts +41 -0
- package/src/bytecodes/votemarket/batchYbVotes.ts +15 -0
- package/src/index.ts +6 -1
- package/src/lockers/fetch/parse.ts +2 -0
- package/src/lockers/fetch/protocols/balancer.ts +3 -0
- package/src/lockers/fetch/protocols/pendle.ts +11 -1
- package/src/prices.ts +4 -0
- package/src/strategies/v2/parse.ts +62 -1
- package/src/votemarket/fetchClaimableData.ts +1 -1
- package/src/votemarket/fetchEpochVotes.ts +14 -4
- package/src/votemarket/generateProofs/config.ts +6 -0
- package/src/votemarket/generateProofs/getGaugeProof.ts +8 -0
- package/src/votemarket/generateProofs/getUserProof.ts +15 -2
- package/src/votemarket/yb/fetchYbUserVotes.ts +61 -0
package/src/prices.ts
CHANGED
|
@@ -35,6 +35,8 @@ export const getLlamaTokenPrefix = (chainId = 1): string => {
|
|
|
35
35
|
return 'avax'
|
|
36
36
|
case 59144:
|
|
37
37
|
return 'linea'
|
|
38
|
+
case 42793:
|
|
39
|
+
return 'etherlink'
|
|
38
40
|
default:
|
|
39
41
|
return 'ethereum'
|
|
40
42
|
}
|
|
@@ -105,6 +107,8 @@ export const getGeckoTerminalTokenPrefix = (chainId = 1): string => {
|
|
|
105
107
|
return 'avax'
|
|
106
108
|
case 59144:
|
|
107
109
|
return 'linea'
|
|
110
|
+
case 42793:
|
|
111
|
+
return 'etherlink'
|
|
108
112
|
default:
|
|
109
113
|
return 'eth'
|
|
110
114
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ONE_YEAR } from '@stake-dao/constants'
|
|
1
2
|
import { getOnlyboostData } from '@stake-dao/reader'
|
|
2
3
|
import { formatUnits, zeroAddress } from 'viem'
|
|
3
4
|
import { arbitrum, base, etherlink, fraxtal, gnosis, mainnet, optimism, sonic } from 'viem/chains'
|
|
@@ -68,6 +69,61 @@ export const parseV2Strats = (global: any, rawStrats: any[], extra: any) => {
|
|
|
68
69
|
yieldType: 'OFFCHAIN',
|
|
69
70
|
}))
|
|
70
71
|
|
|
72
|
+
// Compute rewards from the hook incentive (Votemarket)
|
|
73
|
+
const hookIncentivesPrices = extra?.hookIncentivesPrices || []
|
|
74
|
+
const gaugeUsd = Number(s.gauge.totalSupplyUSD)
|
|
75
|
+
|
|
76
|
+
const incentivesByToken = (extra?.hookIncentives || [])
|
|
77
|
+
.filter((r) => equalTlc(r.vault, s.address))
|
|
78
|
+
.reduce((acc, r) => {
|
|
79
|
+
const rewardAddress = r.reward
|
|
80
|
+
const price = hookIncentivesPrices.find((p) => equalTlc(rewardAddress, p.address))?.usdPrice || 0
|
|
81
|
+
|
|
82
|
+
const amountToken = Number.parseFloat(formatUnits(r.amount, r.rewardDecimals))
|
|
83
|
+
const duration = Number.parseInt(r.end) - Number.parseInt(r.start)
|
|
84
|
+
|
|
85
|
+
if (duration <= 0) return acc
|
|
86
|
+
|
|
87
|
+
const tokensPerSecond = amountToken / duration
|
|
88
|
+
const yearlyTokens = tokensPerSecond * ONE_YEAR
|
|
89
|
+
const yearlyRewardsUsd = yearlyTokens * price
|
|
90
|
+
|
|
91
|
+
if (!acc[rewardAddress]) {
|
|
92
|
+
acc[rewardAddress] = {
|
|
93
|
+
meta: r,
|
|
94
|
+
price: price,
|
|
95
|
+
totalYearlyUsd: 0,
|
|
96
|
+
maxPeriodFinish: Number.parseInt(r.end),
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
acc[rewardAddress].totalYearlyUsd += yearlyRewardsUsd
|
|
101
|
+
acc[rewardAddress].maxPeriodFinish = Math.max(acc[rewardAddress].maxPeriodFinish, Number.parseInt(r.end))
|
|
102
|
+
|
|
103
|
+
return acc
|
|
104
|
+
}, {})
|
|
105
|
+
|
|
106
|
+
const hookIncentives = Object.values(incentivesByToken).map((group: any) => {
|
|
107
|
+
const { meta, price, totalYearlyUsd, maxPeriodFinish } = group
|
|
108
|
+
|
|
109
|
+
const apr = gaugeUsd > 0 ? (totalYearlyUsd / gaugeUsd) * 100 : 0
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
token: parseAsset({
|
|
113
|
+
id: meta.id.toString(),
|
|
114
|
+
name: meta.rewardSymbol,
|
|
115
|
+
symbol: meta.rewardSymbol,
|
|
116
|
+
address: meta.reward,
|
|
117
|
+
decimals: meta.rewardDecimals,
|
|
118
|
+
}),
|
|
119
|
+
aprInToken: price > 0 ? apr / price : 0,
|
|
120
|
+
apr,
|
|
121
|
+
streaming: true,
|
|
122
|
+
periodFinish: maxPeriodFinish,
|
|
123
|
+
yieldType: 'VOTEMARKET',
|
|
124
|
+
}
|
|
125
|
+
})
|
|
126
|
+
|
|
71
127
|
const rewards = otherRewards
|
|
72
128
|
.map((r) => ({
|
|
73
129
|
token: parseAsset(r.asset),
|
|
@@ -78,6 +134,7 @@ export const parseV2Strats = (global: any, rawStrats: any[], extra: any) => {
|
|
|
78
134
|
yieldType: r.yieldType,
|
|
79
135
|
}))
|
|
80
136
|
.concat(merklRewards)
|
|
137
|
+
.concat(hookIncentives)
|
|
81
138
|
.sort((a, b) => {
|
|
82
139
|
if (a.token.address === baseTokens.curve[s.chainId]) return -1
|
|
83
140
|
if (b.token.address === baseTokens.curve[s.chainId]) return 1
|
|
@@ -154,7 +211,11 @@ export const parseV2Strats = (global: any, rawStrats: any[], extra: any) => {
|
|
|
154
211
|
|
|
155
212
|
baseRewardAdded = true
|
|
156
213
|
} else {
|
|
157
|
-
|
|
214
|
+
const label =
|
|
215
|
+
r.yieldType === 'VOTEMARKET'
|
|
216
|
+
? `${r.token.symbol} APR (Extra Rewards from Votemarket)`
|
|
217
|
+
: `${r.token.symbol} APR`
|
|
218
|
+
aprDetails.push({ label, value: [r.apr || 0] })
|
|
158
219
|
}
|
|
159
220
|
}
|
|
160
221
|
|
|
@@ -4,7 +4,7 @@ import batchClaimableData from '../bytecodes/votemarket/batchClaimableData.js'
|
|
|
4
4
|
import { concatBytecode } from '../index.js'
|
|
5
5
|
import { batchJsonRpc } from '../utils.js'
|
|
6
6
|
|
|
7
|
-
const MAX_VOTES_PER_CHUNK =
|
|
7
|
+
const MAX_VOTES_PER_CHUNK = 25
|
|
8
8
|
const MAX_CAMPAIGNS_PER_CHUNKS = 5
|
|
9
9
|
|
|
10
10
|
const chunkCampaignsWithVoteLimit = (campaigns: number[], userVotes: any[]) => {
|
|
@@ -2,11 +2,13 @@ import { contracts } from '@stake-dao/constants'
|
|
|
2
2
|
import { chunk } from 'lodash-es'
|
|
3
3
|
import { encodeAbiParameters, parseAbiParameters } from 'viem'
|
|
4
4
|
import { mainnet } from 'viem/chains'
|
|
5
|
+
import type { BatchMetaData } from '../bytecodes/types.js'
|
|
5
6
|
import batchPendleVotes from '../bytecodes/votemarket/batchPendleVotes.js'
|
|
6
7
|
import batchVotes from '../bytecodes/votemarket/batchVotes.js'
|
|
8
|
+
import batchYbVotes from '../bytecodes/votemarket/batchYbVotes.js'
|
|
7
9
|
import { STAKE_DAO_API } from '../endpoints.js'
|
|
8
10
|
import { concatBytecode } from '../index.js'
|
|
9
|
-
import { batchJsonRpcWithBlocks
|
|
11
|
+
import { batchJsonRpcWithBlocks } from '../utils.js'
|
|
10
12
|
|
|
11
13
|
type Rpcs = {
|
|
12
14
|
[chainId: number]: string
|
|
@@ -37,9 +39,17 @@ export const fetchEpochsVotes = async (rpc: Rpcs, gaugeController: string, user:
|
|
|
37
39
|
// Merge blocks
|
|
38
40
|
const blocksForEpoch = [...cachedBlocks, ...missingBlocks]
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
:
|
|
42
|
+
let batchVotesProtocol: BatchMetaData = batchVotes
|
|
43
|
+
switch (gaugeController.toLowerCase()) {
|
|
44
|
+
case (contracts.pendleGaugeController?.[1] || '').toLowerCase():
|
|
45
|
+
batchVotesProtocol = batchPendleVotes
|
|
46
|
+
break
|
|
47
|
+
case (contracts.ybGaugeController?.[1] || '').toLowerCase():
|
|
48
|
+
batchVotesProtocol = batchYbVotes
|
|
49
|
+
break
|
|
50
|
+
default:
|
|
51
|
+
batchVotesProtocol = batchVotes
|
|
52
|
+
}
|
|
43
53
|
|
|
44
54
|
const inputData = encodeAbiParameters(parseAbiParameters(batchVotesProtocol.inputType[mainnet.id]!) as any, [
|
|
45
55
|
gaugeController,
|
|
@@ -20,12 +20,18 @@ export const GaugeControllerConstants = {
|
|
|
20
20
|
lastUserVote: 1000000010,
|
|
21
21
|
voteUserSlope: 1000000008,
|
|
22
22
|
},
|
|
23
|
+
yb: {
|
|
24
|
+
pointWeights: 1000000006,
|
|
25
|
+
lastUserVote: 1000000005,
|
|
26
|
+
voteUserSlope: 1000000003,
|
|
27
|
+
},
|
|
23
28
|
},
|
|
24
29
|
GAUGE_CONTROLLER: {
|
|
25
30
|
curve: '0x2F50D538606Fa9EDD2B11E2446BEb18C9D5846bB',
|
|
26
31
|
balancer: '0xC128468b7Ce63eA702C1f104D55A2566b13D3ABD',
|
|
27
32
|
frax: '0x3669C421b77340B2979d1A00a792CC2ee0FcE737',
|
|
28
33
|
fxn: '0xe60eB8098B34eD775ac44B1ddE864e098C6d7f37',
|
|
34
|
+
yb: '0x1Be14811A3a06F6aF4fA64310a636e1Df04c1c21',
|
|
29
35
|
},
|
|
30
36
|
}
|
|
31
37
|
|
|
@@ -20,6 +20,13 @@ function getGaugeTimeStorageSlot(gauge: `0x${string}`, time: bigint, baseSlot: n
|
|
|
20
20
|
return BigInt(finalSlot)
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
function getGaugeTimeStorageSlotYb(gauge: `0x${string}`, _: bigint, baseSlot: number): bigint {
|
|
24
|
+
const gaugeEncoded = keccak256(
|
|
25
|
+
encodeAbiParameters([{ type: 'uint256' }, { type: 'address' }], [BigInt(baseSlot), gauge]),
|
|
26
|
+
)
|
|
27
|
+
return BigInt(gaugeEncoded)
|
|
28
|
+
}
|
|
29
|
+
|
|
23
30
|
// Function to get storage slot for Curve protocol (pre-Vyper 0.3)
|
|
24
31
|
function getGaugeTimeStorageSlotPreVyper03(gauge: `0x${string}`, time: bigint, baseSlot: number): bigint {
|
|
25
32
|
const intermediateHash = _encodeGaugeTime(gauge, time, baseSlot)
|
|
@@ -44,6 +51,7 @@ export async function generateGaugeProof(
|
|
|
44
51
|
|
|
45
52
|
const positionFunctions: Record<string, any> = {
|
|
46
53
|
curve: getGaugeTimeStorageSlotPreVyper03,
|
|
54
|
+
yb: getGaugeTimeStorageSlotYb,
|
|
47
55
|
default: getGaugeTimeStorageSlot,
|
|
48
56
|
}
|
|
49
57
|
|
|
@@ -53,10 +53,23 @@ export async function generateUserProof(
|
|
|
53
53
|
const getPosition = positionFunctions[protocol] || positionFunctions.default
|
|
54
54
|
const voteUserSlopeSlot = getPosition(user, gaugeAddress, voteUserSlopeBaseSlot)
|
|
55
55
|
|
|
56
|
+
let index_additionnal_slots = [2n]
|
|
57
|
+
switch (protocol.toLowerCase()) {
|
|
58
|
+
case 'yb':
|
|
59
|
+
index_additionnal_slots = [1n, 3n]
|
|
60
|
+
break
|
|
61
|
+
default:
|
|
62
|
+
index_additionnal_slots = [2n]
|
|
63
|
+
break
|
|
64
|
+
}
|
|
65
|
+
|
|
56
66
|
const voteUserSlopeSlope = voteUserSlopeSlot
|
|
57
|
-
const voteUserSlopeEnd = voteUserSlopeSlot + 2n
|
|
58
67
|
|
|
59
|
-
const slots = [toHex(lastUserVoteSlot), toHex(voteUserSlopeSlope)
|
|
68
|
+
const slots = [toHex(lastUserVoteSlot), toHex(voteUserSlopeSlope)]
|
|
69
|
+
|
|
70
|
+
for (const index_additionnal_slot of index_additionnal_slots) {
|
|
71
|
+
slots.push(toHex(voteUserSlopeSlot + index_additionnal_slot))
|
|
72
|
+
}
|
|
60
73
|
|
|
61
74
|
const proof = await publicClient.getProof({
|
|
62
75
|
address: GaugeControllerConstants.GAUGE_CONTROLLER[protocol] as `0x${string}`,
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { contracts } from '@stake-dao/constants'
|
|
2
|
+
import { encodeAbiParameters, formatUnits, parseAbiParameters, zeroAddress } from 'viem'
|
|
3
|
+
import { mainnet } from 'viem/chains'
|
|
4
|
+
import batchYbUserVotes from '../../bytecodes/votemarket/batchYbUserVotes.js'
|
|
5
|
+
import { concatBytecode } from '../../index.js'
|
|
6
|
+
import { batchJsonRpc, equalTlc } from '../../utils.js'
|
|
7
|
+
|
|
8
|
+
export type Vote = {
|
|
9
|
+
gauge: string
|
|
10
|
+
slope: string
|
|
11
|
+
relativeWeight: number
|
|
12
|
+
weight: number
|
|
13
|
+
start: number
|
|
14
|
+
end: number
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type GaugesUserData = { veBalance: string; unusedVeBalance: string; unusedRelativeWeight: number; votes: Vote[] }
|
|
18
|
+
|
|
19
|
+
export const fetchYbUserVotes = async (rpc: string, user: string): Promise<GaugesUserData> => {
|
|
20
|
+
const calls = [
|
|
21
|
+
concatBytecode(
|
|
22
|
+
batchYbUserVotes.bytecode[mainnet.id]!,
|
|
23
|
+
encodeAbiParameters(parseAbiParameters(batchYbUserVotes.inputType[mainnet.id]!) as any, [
|
|
24
|
+
user,
|
|
25
|
+
contracts.ybGaugeController![1]!,
|
|
26
|
+
contracts.veYB![1]!,
|
|
27
|
+
]),
|
|
28
|
+
),
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
const rawVotes = await batchJsonRpc({
|
|
32
|
+
rpc,
|
|
33
|
+
calls,
|
|
34
|
+
outputTypeAbi: batchYbUserVotes.outputType![mainnet.id],
|
|
35
|
+
parse: false,
|
|
36
|
+
callsKey: `votemarket/yb/fetchYbUserVotes.ts: rawGauges - chainId ${mainnet.id} - rpc ${rpc}`,
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
const veBalance = rawVotes[0].veBalance
|
|
40
|
+
|
|
41
|
+
const votes = rawVotes[0].votes
|
|
42
|
+
.filter((rv) => !equalTlc(rv.gauge, zeroAddress))
|
|
43
|
+
.map((v) => ({
|
|
44
|
+
gauge: v.gauge,
|
|
45
|
+
slope: formatUnits(v.slope, 0),
|
|
46
|
+
relativeWeight: Number(v.power) / 100,
|
|
47
|
+
weight: formatUnits((veBalance * BigInt(v.power)) / BigInt(10000), 18),
|
|
48
|
+
start: Number(v.start),
|
|
49
|
+
end: Number(v.end),
|
|
50
|
+
}))
|
|
51
|
+
|
|
52
|
+
const unusedRelativeWeight = 10000 - votes.reduce((total, x) => total + x.relativeWeight * 100, 0)
|
|
53
|
+
const unusedVeBalance = (veBalance * BigInt(unusedRelativeWeight)) / BigInt(10000)
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
veBalance: formatUnits(veBalance, 18),
|
|
57
|
+
unusedVeBalance: formatUnits(unusedVeBalance, 18),
|
|
58
|
+
unusedRelativeWeight: unusedRelativeWeight / 100,
|
|
59
|
+
votes,
|
|
60
|
+
}
|
|
61
|
+
}
|