@stake-dao/reader 0.4.32 → 0.4.33
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/bytecodes/index.js +1 -0
- package/dist/esm/bytecodes/index.js.map +1 -1
- package/dist/esm/bytecodes/votemarket/getNeededCampaignUpdate.js +17 -0
- package/dist/esm/bytecodes/votemarket/getNeededCampaignUpdate.js.map +1 -0
- package/dist/esm/endpoints.js +1 -0
- package/dist/esm/endpoints.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/strategies/pancakeswap/fetch/getPancakeV3Vaults.js +1 -1
- package/dist/esm/strategies/pancakeswap/fetch/getPancakeV3Vaults.js.map +1 -1
- package/dist/esm/strategies/pancakeswap/fetch/pancakePositions.js +2 -2
- package/dist/esm/strategies/pancakeswap/fetch/pancakePositions.js.map +1 -1
- package/dist/esm/strategies/pancakeswap/fetch/pancakeswapMath.js +1 -1
- package/dist/esm/strategies/pancakeswap/fetch/pancakeswapMath.js.map +1 -1
- package/dist/esm/tsconfig.build.tsbuildinfo +1 -1
- package/dist/esm/votemarket/curve/fetchCurveGauges.js +4 -1
- package/dist/esm/votemarket/curve/fetchCurveGauges.js.map +1 -1
- package/dist/esm/votemarket/curve/fetchSnapshotUserData.js +34 -1
- package/dist/esm/votemarket/curve/fetchSnapshotUserData.js.map +1 -1
- package/dist/esm/votemarket/curve/fetchUserVlCvxClaimable.js +37 -5
- package/dist/esm/votemarket/curve/fetchUserVlCvxClaimable.js.map +1 -1
- package/dist/esm/votemarket/fetchCampaigns.js +4 -4
- package/dist/esm/votemarket/fetchCampaigns.js.map +1 -1
- package/dist/esm/votemarket/fetchNeededCampaignUpdate.js +17 -0
- package/dist/esm/votemarket/fetchNeededCampaignUpdate.js.map +1 -0
- package/dist/types/bytecodes/index.d.ts +1 -0
- package/dist/types/bytecodes/index.d.ts.map +1 -1
- package/dist/types/bytecodes/votemarket/getNeededCampaignUpdate.d.ts +4 -0
- package/dist/types/bytecodes/votemarket/getNeededCampaignUpdate.d.ts.map +1 -0
- package/dist/types/endpoints.d.ts +1 -0
- package/dist/types/endpoints.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/strategies/pancakeswap/fetch/pancakeswapMath.d.ts.map +1 -1
- package/dist/types/votemarket/curve/fetchCurveGauges.d.ts.map +1 -1
- package/dist/types/votemarket/curve/fetchSnapshotUserData.d.ts +6 -0
- package/dist/types/votemarket/curve/fetchSnapshotUserData.d.ts.map +1 -1
- package/dist/types/votemarket/curve/fetchUserVlCvxClaimable.d.ts.map +1 -1
- package/dist/types/votemarket/fetchNeededCampaignUpdate.d.ts +2 -0
- package/dist/types/votemarket/fetchNeededCampaignUpdate.d.ts.map +1 -0
- package/package.json +2 -2
- package/src/bytecodes/index.ts +1 -0
- package/src/bytecodes/votemarket/getNeededCampaignUpdate.ts +19 -0
- package/src/endpoints.ts +2 -0
- package/src/index.ts +1 -0
- package/src/strategies/pancakeswap/fetch/getPancakeV3Vaults.ts +1 -1
- package/src/strategies/pancakeswap/fetch/pancakePositions.ts +2 -2
- package/src/strategies/pancakeswap/fetch/pancakeswapMath.ts +1 -1
- package/src/votemarket/curve/fetchCurveGauges.ts +5 -1
- package/src/votemarket/curve/fetchSnapshotUserData.ts +43 -3
- package/src/votemarket/curve/fetchUserVlCvxClaimable.ts +51 -6
- package/src/votemarket/fetchCampaigns.ts +4 -4
- package/src/votemarket/fetchNeededCampaignUpdate.ts +28 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import snapshot from '@snapshot-labs/snapshot.js'
|
|
2
2
|
import { gql } from 'graphql-request'
|
|
3
3
|
import { isAddress } from 'viem'
|
|
4
|
+
import { SNAPSHOT_HUB } from '../../endpoints.js'
|
|
4
5
|
import { graphql } from '../../utils.js'
|
|
5
6
|
|
|
6
7
|
interface SnapshotProposal {
|
|
@@ -21,6 +22,7 @@ interface ISnapshotUserData {
|
|
|
21
22
|
proposal: SnapshotProposal
|
|
22
23
|
vp: number
|
|
23
24
|
space: string
|
|
25
|
+
userVotes: { [gaugeId: string]: { weight: number; relativeWeight: number } }
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
interface SnapshotStrategy {
|
|
@@ -66,6 +68,24 @@ query Proposals {
|
|
|
66
68
|
}
|
|
67
69
|
`
|
|
68
70
|
|
|
71
|
+
const SNAPSHOT_USER_VOTE_QUERY = (space: string, proposal: string, user: string) => gql`
|
|
72
|
+
query UserVote {
|
|
73
|
+
votes (
|
|
74
|
+
first: 1
|
|
75
|
+
where: {
|
|
76
|
+
space: "${space}"
|
|
77
|
+
proposal: "${proposal}"
|
|
78
|
+
voter: "${user}"
|
|
79
|
+
}
|
|
80
|
+
) {
|
|
81
|
+
id
|
|
82
|
+
created
|
|
83
|
+
choice
|
|
84
|
+
vp
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
`
|
|
88
|
+
|
|
69
89
|
export const fetchSnapshotUserData = async (
|
|
70
90
|
userAddress: string,
|
|
71
91
|
spaces: string[],
|
|
@@ -74,9 +94,7 @@ export const fetchSnapshotUserData = async (
|
|
|
74
94
|
return undefined
|
|
75
95
|
}
|
|
76
96
|
|
|
77
|
-
const responses = await Promise.all(
|
|
78
|
-
spaces.map((space) => graphql('https://hub.snapshot.org/graphql', SNAPSHOT_PROPOSAL_QUERY(space))),
|
|
79
|
-
)
|
|
97
|
+
const responses = await Promise.all(spaces.map((space) => graphql(SNAPSHOT_HUB, SNAPSHOT_PROPOSAL_QUERY(space))))
|
|
80
98
|
|
|
81
99
|
const results: ISnapshotUserData[] = []
|
|
82
100
|
for (let i = 0; i < responses.length; i++) {
|
|
@@ -94,6 +112,7 @@ export const fetchSnapshotUserData = async (
|
|
|
94
112
|
|
|
95
113
|
// Fetch user voting power
|
|
96
114
|
let vp = 0
|
|
115
|
+
const userVotes = {}
|
|
97
116
|
if (isAddress(userAddress)) {
|
|
98
117
|
const fetchedVp = await (snapshot as any).utils.getScores(
|
|
99
118
|
spaces[i],
|
|
@@ -108,12 +127,33 @@ export const fetchSnapshotUserData = async (
|
|
|
108
127
|
vp += v?.[userAddress] || 0
|
|
109
128
|
}
|
|
110
129
|
}
|
|
130
|
+
|
|
131
|
+
const rawUserVotes = await graphql(SNAPSHOT_HUB, SNAPSHOT_USER_VOTE_QUERY(spaces[i]!, proposal.id, userAddress))
|
|
132
|
+
|
|
133
|
+
if (rawUserVotes?.votes && rawUserVotes.votes.length > 0) {
|
|
134
|
+
const rawUserVote = rawUserVotes.votes[0]
|
|
135
|
+
const totalSnapshotVote = Object.keys(rawUserVote.choice).reduce(
|
|
136
|
+
(total, i) => (total += rawUserVote.choice[i]),
|
|
137
|
+
0,
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
for (const i of Object.keys(rawUserVote.choice)) {
|
|
141
|
+
const relativeWeight = rawUserVote.choice[i] / totalSnapshotVote
|
|
142
|
+
const proposalChoiceIndex = Number(i) - 1
|
|
143
|
+
|
|
144
|
+
userVotes[proposal.choices[proposalChoiceIndex]!] = {
|
|
145
|
+
weight: rawUserVote.vp * relativeWeight,
|
|
146
|
+
relativeWeight: relativeWeight * 100,
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
111
150
|
}
|
|
112
151
|
|
|
113
152
|
results.push({
|
|
114
153
|
proposal,
|
|
115
154
|
space: spaces[i] as string,
|
|
116
155
|
vp,
|
|
156
|
+
userVotes,
|
|
117
157
|
})
|
|
118
158
|
}
|
|
119
159
|
|
|
@@ -19,9 +19,39 @@ type UnknownToken = {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
const getMerkleData = async (epoch: number) => {
|
|
22
|
-
|
|
22
|
+
const response = await fetch(
|
|
23
23
|
`${GH_STAKE_DAO_BOUNTIES_REPORT}/refs/heads/main/bounties-reports/${epoch}/vlCVX/merkle_data.json`,
|
|
24
|
-
)
|
|
24
|
+
)
|
|
25
|
+
if (!response.ok) throw new Error('Failed to fetch merkle data')
|
|
26
|
+
return response.json()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const isRootMatch = (contractRoot: string, fileRoot: string) =>
|
|
30
|
+
(contractRoot === ZERO_ROOT && fileRoot === ZERO_ROOT) || contractRoot.toLowerCase() === fileRoot.toLowerCase()
|
|
31
|
+
|
|
32
|
+
const validateMerkleRoots = (delegatorRoot: string, nonDelegatorRoot: string, merkleData: any) => {
|
|
33
|
+
const delegatorMatches = isRootMatch(delegatorRoot, merkleData.delegators.merkleRoot)
|
|
34
|
+
const nonDelegatorMatches = isRootMatch(nonDelegatorRoot, merkleData.nonDelegators.merkleRoot)
|
|
35
|
+
return delegatorMatches || nonDelegatorMatches
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const getMerkleRoots = async (provider: any) => {
|
|
39
|
+
const contracts = [contract('vlCvxDelegatorMerkle', mainnet.id), contract('vlCvxNotDelegatorMerkle', mainnet.id)]
|
|
40
|
+
|
|
41
|
+
const result = await multicall(
|
|
42
|
+
provider,
|
|
43
|
+
contracts.map((address) => ({
|
|
44
|
+
address,
|
|
45
|
+
name: 'root',
|
|
46
|
+
params: [],
|
|
47
|
+
})),
|
|
48
|
+
parseAbi(['function root() external view returns (bytes32)']),
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
delegatorRoot: result[0].result,
|
|
53
|
+
nonDelegatorRoot: result[1].result,
|
|
54
|
+
}
|
|
25
55
|
}
|
|
26
56
|
|
|
27
57
|
const getClaimedData = async (provider: any, tokens: string[], user: string, contract: string) => {
|
|
@@ -74,14 +104,29 @@ const getParsedData = (
|
|
|
74
104
|
: undefined
|
|
75
105
|
}
|
|
76
106
|
|
|
107
|
+
const ZERO_ROOT = '0x0000000000000000000000000000000000000000000000000000000000000000'
|
|
108
|
+
|
|
77
109
|
export const fetchUserVlCvxClaimable = async (provider: any, rpc: Rpcs, user: string) => {
|
|
78
110
|
const nowEpoch = Math.floor(Date.now() / (1000 * ONE_WEEK)) * ONE_WEEK
|
|
111
|
+
const prevEpoch = nowEpoch - ONE_WEEK
|
|
112
|
+
|
|
113
|
+
const { delegatorRoot, nonDelegatorRoot } = await getMerkleRoots(provider)
|
|
79
114
|
|
|
80
115
|
let vlCvxClaimable: any
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
116
|
+
|
|
117
|
+
// Try current week, then previous week if needed
|
|
118
|
+
for (const epoch of [nowEpoch, prevEpoch]) {
|
|
119
|
+
try {
|
|
120
|
+
const merkleData = await getMerkleData(epoch)
|
|
121
|
+
if (validateMerkleRoots(delegatorRoot, nonDelegatorRoot, merkleData)) {
|
|
122
|
+
vlCvxClaimable = merkleData
|
|
123
|
+
break
|
|
124
|
+
}
|
|
125
|
+
} catch {}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (!vlCvxClaimable) {
|
|
129
|
+
throw new Error('Could not find valid merkle data')
|
|
85
130
|
}
|
|
86
131
|
|
|
87
132
|
const vlCvxUserDelegated = vlCvxClaimable?.delegators.claims[user]
|
|
@@ -161,10 +161,10 @@ export const fetchCampaigns = async ({ platform, chainId, rpcs }: FetchCampaigns
|
|
|
161
161
|
const prices = [
|
|
162
162
|
...(fetchedTokens.length > 0 ? await getPrices(fetchedTokens as any, chainId) : []),
|
|
163
163
|
...(nativeFetchedTokens.length > 0 ? await getPrices(nativeFetchedTokens as any, mainnet.id) : []),
|
|
164
|
-
{ address: '0x9E49A0314AE61e9C9E34e4Af62a73FBFfB6DE95A', symbol: 'ARR', usdPrice: 10 }, // For test purpose
|
|
165
|
-
{ address: '0x0Cc20784f790805537D4eE33B41f1aC4eC55446B', symbol: 'USDC', usdPrice: 1 }, // For test purpose
|
|
166
|
-
{ address: '0x59c9a01163e685719FAbE5De34779F563f49D4a3', symbol: 'CRV', usdPrice: 30 }, // For test purpose
|
|
167
|
-
{ address: '0x3c7b193aa39a85FDE911465d35CE3A74499F0A7B', symbol: 'ARR', usdPrice: 10 }, // For test purpose
|
|
164
|
+
// { address: '0x9E49A0314AE61e9C9E34e4Af62a73FBFfB6DE95A', symbol: 'ARR', usdPrice: 10 }, // For test purpose
|
|
165
|
+
// { address: '0x0Cc20784f790805537D4eE33B41f1aC4eC55446B', symbol: 'USDC', usdPrice: 1 }, // For test purpose
|
|
166
|
+
// { address: '0x59c9a01163e685719FAbE5De34779F563f49D4a3', symbol: 'CRV', usdPrice: 30 }, // For test purpose
|
|
167
|
+
// { address: '0x3c7b193aa39a85FDE911465d35CE3A74499F0A7B', symbol: 'ARR', usdPrice: 10 }, // For test purpose
|
|
168
168
|
]
|
|
169
169
|
|
|
170
170
|
const allFetchedTokens = [...fetchedTokens, ...nativeFetchedTokens]
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { encodeAbiParameters, parseAbiParameters } from 'viem'
|
|
2
|
+
import { mainnet } from 'viem/chains'
|
|
3
|
+
import { getNeededCampaignUpdate } from '../bytecodes/index.js'
|
|
4
|
+
import { concatBytecode } from '../index.js'
|
|
5
|
+
import { batchJsonRpc } from '../utils.js'
|
|
6
|
+
|
|
7
|
+
export const fetchNeededCampaignUpdate = async (rpc: string, platform: string, campaign: any) => {
|
|
8
|
+
const inputData = encodeAbiParameters(
|
|
9
|
+
parseAbiParameters(
|
|
10
|
+
getNeededCampaignUpdate.inputType[campaign.chainId] || getNeededCampaignUpdate.inputType[mainnet.id]!,
|
|
11
|
+
) as any,
|
|
12
|
+
[platform, campaign.id],
|
|
13
|
+
)
|
|
14
|
+
const call = concatBytecode(
|
|
15
|
+
getNeededCampaignUpdate.bytecode[campaign.chainId] || getNeededCampaignUpdate.bytecode[mainnet.id]!,
|
|
16
|
+
inputData,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
const neededForUpdate = await batchJsonRpc({
|
|
20
|
+
rpc,
|
|
21
|
+
calls: [call],
|
|
22
|
+
outputTypeAbi:
|
|
23
|
+
getNeededCampaignUpdate.outputTypeHr[campaign.chainId] || getNeededCampaignUpdate.outputTypeHr[mainnet.id]!,
|
|
24
|
+
callsKey: `Get needed update - chainId ${campaign.chainId} - rpc ${rpc}`,
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
return neededForUpdate
|
|
28
|
+
}
|