@stake-dao/reader 0.4.30 → 0.4.32

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.
Files changed (182) hide show
  1. package/dist/esm/bytecodes/ccipFee.js +11 -0
  2. package/dist/esm/bytecodes/ccipFee.js.map +1 -0
  3. package/dist/esm/bytecodes/gaugeManager/curveGaugeRewardsData.js +1 -1
  4. package/dist/esm/bytecodes/gaugeManager/curveGaugeRewardsData.js.map +1 -1
  5. package/dist/esm/bytecodes/votemarket/batchCampaigns.js +5 -3
  6. package/dist/esm/bytecodes/votemarket/batchCampaigns.js.map +1 -1
  7. package/dist/esm/bytecodes/votemarket/curve/batchCurveGauges.js +3 -2
  8. package/dist/esm/bytecodes/votemarket/curve/batchCurveGauges.js.map +1 -1
  9. package/dist/esm/ccip/fetchCcipFee.js +25 -0
  10. package/dist/esm/ccip/fetchCcipFee.js.map +1 -0
  11. package/dist/esm/endpoints.js +3 -0
  12. package/dist/esm/endpoints.js.map +1 -1
  13. package/dist/esm/index.js +8 -0
  14. package/dist/esm/index.js.map +1 -1
  15. package/dist/esm/lockers/fetch/index.js +7 -4
  16. package/dist/esm/lockers/fetch/index.js.map +1 -1
  17. package/dist/esm/lockers/fetch/parseBoost.js +13 -0
  18. package/dist/esm/lockers/fetch/parseBoost.js.map +1 -0
  19. package/dist/esm/lockers/utils/cakeLockerAirdrop.js +1 -1
  20. package/dist/esm/lockers/utils/cakeLockerAirdrop.js.map +1 -1
  21. package/dist/esm/lockers/utils/callsForLockers/index.js +4 -3
  22. package/dist/esm/lockers/utils/callsForLockers/index.js.map +1 -1
  23. package/dist/esm/lockers/utils/callsForLockers/pegCalls.js +1 -2
  24. package/dist/esm/lockers/utils/callsForLockers/pegCalls.js.map +1 -1
  25. package/dist/esm/lockers/utils/callsForLockers/veBoosts.js +9 -0
  26. package/dist/esm/lockers/utils/callsForLockers/veBoosts.js.map +1 -0
  27. package/dist/esm/lockers/utils/getBribesRewardsData.js +1 -2
  28. package/dist/esm/lockers/utils/getBribesRewardsData.js.map +1 -1
  29. package/dist/esm/lockers/utils/getHttpCalls.js +3 -2
  30. package/dist/esm/lockers/utils/getHttpCalls.js.map +1 -1
  31. package/dist/esm/lockers/utils/index.js +1 -1
  32. package/dist/esm/lockers/utils/index.js.map +1 -1
  33. package/dist/esm/prices.js +17 -21
  34. package/dist/esm/prices.js.map +1 -1
  35. package/dist/esm/sdt/fetch.js +1 -2
  36. package/dist/esm/sdt/fetch.js.map +1 -1
  37. package/dist/esm/sdt.js +1 -5
  38. package/dist/esm/sdt.js.map +1 -1
  39. package/dist/esm/strategies/angle/fetch.js +1 -2
  40. package/dist/esm/strategies/angle/fetch.js.map +1 -1
  41. package/dist/esm/strategies/balancer/fetch.js +2 -2
  42. package/dist/esm/strategies/balancer/fetch.js.map +1 -1
  43. package/dist/esm/strategies/curve/build.js +5 -13
  44. package/dist/esm/strategies/curve/build.js.map +1 -1
  45. package/dist/esm/strategies/curve/fetch/curveApiData/getCurveApiData.js +2 -2
  46. package/dist/esm/strategies/curve/fetch/curveApiData/getCurveApiData.js.map +1 -1
  47. package/dist/esm/strategies/curve/fetch/getCvxApr.js +1 -1
  48. package/dist/esm/strategies/curve/fetch/getCvxApr.js.map +1 -1
  49. package/dist/esm/strategies/curve/fetch/index.js +1 -2
  50. package/dist/esm/strategies/curve/fetch/index.js.map +1 -1
  51. package/dist/esm/strategies/pancakeswap/endpoints.js +2 -1
  52. package/dist/esm/strategies/pancakeswap/endpoints.js.map +1 -1
  53. package/dist/esm/strategies/pancakeswap/fetch/getPancakeV3Vaults.js +2 -2
  54. package/dist/esm/strategies/pancakeswap/fetch/index.js +2 -1
  55. package/dist/esm/strategies/pancakeswap/fetch/index.js.map +1 -1
  56. package/dist/esm/strategies/pancakeswap/fetch/pancakeswapMath.js +2 -3
  57. package/dist/esm/strategies/pancakeswap/fetch/pancakeswapMath.js.map +1 -1
  58. package/dist/esm/strategies/pendle/fetch.js +2 -2
  59. package/dist/esm/strategies/pendle/fetch.js.map +1 -1
  60. package/dist/esm/strategies/utils/boost.js +1 -1
  61. package/dist/esm/strategies/utils/boost.js.map +1 -1
  62. package/dist/esm/strategies/utils/index.js +1 -4
  63. package/dist/esm/strategies/utils/index.js.map +1 -1
  64. package/dist/esm/strategies/yearn/build.js +5 -13
  65. package/dist/esm/strategies/yearn/build.js.map +1 -1
  66. package/dist/esm/strategies/yearn/fetch/index.js +2 -2
  67. package/dist/esm/strategies/yearn/fetch/index.js.map +1 -1
  68. package/dist/esm/tokens.js +34 -0
  69. package/dist/esm/tokens.js.map +1 -0
  70. package/dist/esm/tsconfig.build.tsbuildinfo +1 -1
  71. package/dist/esm/utils.js +27 -24
  72. package/dist/esm/utils.js.map +1 -1
  73. package/dist/esm/votemarket/curve/config.js +12 -1
  74. package/dist/esm/votemarket/curve/config.js.map +1 -1
  75. package/dist/esm/votemarket/curve/fetchCurveGauges.js +5 -3
  76. package/dist/esm/votemarket/curve/fetchCurveGauges.js.map +1 -1
  77. package/dist/esm/votemarket/curve/fetchCurveUserVotes.js +1 -1
  78. package/dist/esm/votemarket/curve/fetchCurveUserVotes.js.map +1 -1
  79. package/dist/esm/votemarket/curve/fetchUserVlCvxClaimable.js +81 -0
  80. package/dist/esm/votemarket/curve/fetchUserVlCvxClaimable.js.map +1 -0
  81. package/dist/esm/votemarket/fetchCampaigns.js +46 -49
  82. package/dist/esm/votemarket/fetchCampaigns.js.map +1 -1
  83. package/dist/esm/votemarket/fetchClaimableData.js +7 -12
  84. package/dist/esm/votemarket/fetchClaimableData.js.map +1 -1
  85. package/dist/esm/votemarket/generateProofs/getBlockProof.js +2 -1
  86. package/dist/esm/votemarket/generateProofs/getBlockProof.js.map +1 -1
  87. package/dist/types/bytecodes/ccipFee.d.ts +4 -0
  88. package/dist/types/bytecodes/ccipFee.d.ts.map +1 -0
  89. package/dist/types/bytecodes/votemarket/batchCampaigns.d.ts.map +1 -1
  90. package/dist/types/bytecodes/votemarket/curve/batchCurveGauges.d.ts.map +1 -1
  91. package/dist/types/ccip/fetchCcipFee.d.ts +15 -0
  92. package/dist/types/ccip/fetchCcipFee.d.ts.map +1 -0
  93. package/dist/types/endpoints.d.ts +3 -0
  94. package/dist/types/endpoints.d.ts.map +1 -1
  95. package/dist/types/index.d.ts +2 -0
  96. package/dist/types/index.d.ts.map +1 -1
  97. package/dist/types/lockers/fetch/index.d.ts +1 -0
  98. package/dist/types/lockers/fetch/index.d.ts.map +1 -1
  99. package/dist/types/lockers/fetch/parseBoost.d.ts +3 -0
  100. package/dist/types/lockers/fetch/parseBoost.d.ts.map +1 -0
  101. package/dist/types/lockers/utils/callsForLockers/index.d.ts +5 -1
  102. package/dist/types/lockers/utils/callsForLockers/index.d.ts.map +1 -1
  103. package/dist/types/lockers/utils/callsForLockers/pegCalls.d.ts.map +1 -1
  104. package/dist/types/lockers/utils/callsForLockers/veBoosts.d.ts +7 -0
  105. package/dist/types/lockers/utils/callsForLockers/veBoosts.d.ts.map +1 -0
  106. package/dist/types/lockers/utils/getBribesRewardsData.d.ts.map +1 -1
  107. package/dist/types/lockers/utils/getHttpCalls.d.ts.map +1 -1
  108. package/dist/types/prices.d.ts +1 -0
  109. package/dist/types/prices.d.ts.map +1 -1
  110. package/dist/types/sdt/fetch.d.ts.map +1 -1
  111. package/dist/types/sdt.d.ts.map +1 -1
  112. package/dist/types/strategies/angle/fetch.d.ts.map +1 -1
  113. package/dist/types/strategies/balancer/fetch.d.ts.map +1 -1
  114. package/dist/types/strategies/curve/build.d.ts.map +1 -1
  115. package/dist/types/strategies/curve/fetch/index.d.ts.map +1 -1
  116. package/dist/types/strategies/pancakeswap/endpoints.d.ts.map +1 -1
  117. package/dist/types/strategies/pancakeswap/fetch/index.d.ts.map +1 -1
  118. package/dist/types/strategies/pancakeswap/fetch/pancakeswapMath.d.ts.map +1 -1
  119. package/dist/types/strategies/pendle/fetch.d.ts.map +1 -1
  120. package/dist/types/strategies/utils/index.d.ts +0 -3
  121. package/dist/types/strategies/utils/index.d.ts.map +1 -1
  122. package/dist/types/strategies/yearn/build.d.ts.map +1 -1
  123. package/dist/types/tokens.d.ts +3 -0
  124. package/dist/types/tokens.d.ts.map +1 -0
  125. package/dist/types/utils.d.ts.map +1 -1
  126. package/dist/types/votemarket/curve/config.d.ts +12 -1
  127. package/dist/types/votemarket/curve/config.d.ts.map +1 -1
  128. package/dist/types/votemarket/curve/fetchCurveGauges.d.ts.map +1 -1
  129. package/dist/types/votemarket/curve/fetchUserVlCvxClaimable.d.ts +16 -0
  130. package/dist/types/votemarket/curve/fetchUserVlCvxClaimable.d.ts.map +1 -0
  131. package/dist/types/votemarket/fetchCampaigns.d.ts +4 -2
  132. package/dist/types/votemarket/fetchCampaigns.d.ts.map +1 -1
  133. package/dist/types/votemarket/fetchClaimableData.d.ts +1 -5
  134. package/dist/types/votemarket/fetchClaimableData.d.ts.map +1 -1
  135. package/dist/types/votemarket/generateProofs/getBlockProof.d.ts.map +1 -1
  136. package/dist/types/votemarket/types.d.ts +9 -1
  137. package/dist/types/votemarket/types.d.ts.map +1 -1
  138. package/package.json +2 -2
  139. package/src/bytecodes/ccipFee.ts +14 -0
  140. package/src/bytecodes/gaugeManager/curveGaugeRewardsData.ts +1 -1
  141. package/src/bytecodes/votemarket/batchCampaigns.ts +5 -3
  142. package/src/bytecodes/votemarket/curve/batchCurveGauges.ts +3 -2
  143. package/src/ccip/fetchCcipFee.ts +46 -0
  144. package/src/endpoints.ts +4 -0
  145. package/src/index.ts +13 -0
  146. package/src/lockers/fetch/index.ts +8 -2
  147. package/src/lockers/fetch/parseBoost.ts +13 -0
  148. package/src/lockers/utils/cakeLockerAirdrop.ts +1 -1
  149. package/src/lockers/utils/callsForLockers/index.ts +7 -2
  150. package/src/lockers/utils/callsForLockers/pegCalls.ts +1 -2
  151. package/src/lockers/utils/callsForLockers/veBoosts.ts +15 -0
  152. package/src/lockers/utils/getBribesRewardsData.ts +1 -2
  153. package/src/lockers/utils/getHttpCalls.ts +3 -2
  154. package/src/lockers/utils/index.ts +1 -1
  155. package/src/prices.ts +18 -21
  156. package/src/sdt/fetch.ts +1 -2
  157. package/src/sdt.ts +10 -5
  158. package/src/strategies/angle/fetch.ts +1 -2
  159. package/src/strategies/balancer/fetch.ts +3 -1
  160. package/src/strategies/curve/build.ts +6 -20
  161. package/src/strategies/curve/fetch/curveApiData/getCurveApiData.ts +2 -2
  162. package/src/strategies/curve/fetch/getCvxApr.ts +1 -1
  163. package/src/strategies/curve/fetch/index.ts +1 -2
  164. package/src/strategies/pancakeswap/endpoints.ts +3 -2
  165. package/src/strategies/pancakeswap/fetch/getPancakeV3Vaults.ts +2 -2
  166. package/src/strategies/pancakeswap/fetch/index.ts +2 -1
  167. package/src/strategies/pancakeswap/fetch/pancakeswapMath.ts +2 -3
  168. package/src/strategies/pendle/fetch.ts +12 -2
  169. package/src/strategies/utils/boost.ts +1 -1
  170. package/src/strategies/utils/index.ts +1 -5
  171. package/src/strategies/yearn/build.ts +6 -20
  172. package/src/strategies/yearn/fetch/index.ts +2 -2
  173. package/src/tokens.ts +44 -0
  174. package/src/utils.ts +41 -29
  175. package/src/votemarket/curve/config.ts +12 -1
  176. package/src/votemarket/curve/fetchCurveGauges.ts +5 -3
  177. package/src/votemarket/curve/fetchCurveUserVotes.ts +1 -1
  178. package/src/votemarket/curve/fetchUserVlCvxClaimable.ts +132 -0
  179. package/src/votemarket/fetchCampaigns.ts +61 -55
  180. package/src/votemarket/fetchClaimableData.ts +11 -16
  181. package/src/votemarket/generateProofs/getBlockProof.ts +2 -1
  182. package/src/votemarket/types.ts +9 -1
@@ -1,9 +1,10 @@
1
- import { chunk, remove, uniq } from 'lodash-es'
1
+ import { chunk } from 'lodash-es'
2
2
  import { decodeAbiParameters, encodeAbiParameters, parseAbiParameters } from 'viem'
3
3
 
4
- import { contracts, tokens } from '@stake-dao/constants'
5
- import type { FetchedToken, Token } from '@stake-dao/constants'
6
- import { batchSdtGaugeRewards, batchTokenData, buildYearnStrats } from '../../bytecodes/index.js'
4
+ import { contracts } from '@stake-dao/constants'
5
+ import type { FetchedToken } from '@stake-dao/constants'
6
+ import { batchSdtGaugeRewards, buildYearnStrats } from '../../bytecodes/index.js'
7
+ import { fetchTokensData } from '../../tokens.js'
7
8
  import { equalTlc, getTokenInfo } from '../../utils.js'
8
9
  import type { BuiltStrat } from '../types.js'
9
10
  import { concatBytecode } from '../utils/index.js'
@@ -67,22 +68,7 @@ export const buildYearnStrategies = async (
67
68
  })
68
69
 
69
70
  // Fetch tokens infos
70
- const tokensInputArgsChunks = chunk(
71
- remove(uniq(tokensToFetch), (t) => !tokens.find((token: Token) => token.address === t)),
72
- 40,
73
- )
74
- const decodedPromise = await Promise.allSettled(
75
- tokensInputArgsChunks.map(async (inputArgs) => {
76
- const inputData = encodeAbiParameters(parseAbiParameters(batchTokenData.inputType || []) as any, [inputArgs])
77
- const contractCreationCode = concatBytecode(batchTokenData.bytecode, inputData)
78
- const returnedData = await provider.call({
79
- data: contractCreationCode,
80
- })
81
- return decodeAbiParameters(parseAbiParameters(batchTokenData.outputTypeHr || []) as any, returnedData.data)
82
- }),
83
- )
84
-
85
- const fetchedTokenData = decodedPromise.flatMap((d) => (d.status === 'fulfilled' ? d.value : [])).flat()
71
+ const fetchedTokenData = await fetchTokensData(provider, tokensToFetch)
86
72
 
87
73
  // Fetch Sdt Gauge rewards tokens infos
88
74
  const sdtGaugeInputArgsChunks = chunk(
@@ -1,7 +1,7 @@
1
1
  import { chunk } from 'lodash-es'
2
2
  import { formatUnits } from 'viem'
3
3
 
4
- import { ONE_YEAR, yearnStrats } from '@stake-dao/constants'
4
+ import { ONE_YEAR, OneEther, Zero, yearnStrats } from '@stake-dao/constants'
5
5
  import multicallYearnStratsAbi from '../../../abis/yearnVaultsMulticall.js'
6
6
  import { equalTlc, multicall } from '../../../utils.js'
7
7
  import { NEW_FACTORY_EXPLORER_EVENTS } from '../../curve/endpoints.js'
@@ -14,7 +14,7 @@ import type { Price } from '../../../prices.js'
14
14
  import { type SdtEmissionData, getSdtApr } from '../../../sdt.js'
15
15
  import type { RewardsData, StrategyData, ValidChainId, ValidExplorer } from '../../types.js'
16
16
  import { getAprBreakdown } from '../../utils/getAprBreakdown.js'
17
- import { OneEther, Zero, decodeNewFactoryEvent } from '../../utils/index.js'
17
+ import { decodeNewFactoryEvent } from '../../utils/index.js'
18
18
  import { fetchAllYearnGauges } from './fetchAllYearnGauges.js'
19
19
 
20
20
  const globalCalls = [
package/src/tokens.ts ADDED
@@ -0,0 +1,44 @@
1
+ import { type Token, tokens } from '@stake-dao/constants'
2
+ import { chunk, remove, uniq } from 'lodash-es'
3
+ import { decodeAbiParameters, encodeAbiParameters, parseAbiParameters } from 'viem'
4
+ import { batchTokenData } from './bytecodes/index.js'
5
+ import { batchJsonRpc, concatBytecode } from './utils.js'
6
+
7
+ export const fetchTokensData = async (provider: any, tokensToFetch: string[]) => {
8
+ const inputArgsChunks = chunk(
9
+ remove(uniq(tokensToFetch), (t) => !tokens.find((token: Token) => token.address === t)),
10
+ 40,
11
+ )
12
+ const decodedPromise = await Promise.allSettled(
13
+ inputArgsChunks.map(async (inputArgs) => {
14
+ const inputData = encodeAbiParameters(parseAbiParameters(batchTokenData.inputType || []) as any, [inputArgs])
15
+ const contractCreationCode = concatBytecode(batchTokenData.bytecode, inputData)
16
+ const returnedData = await provider.call({
17
+ data: contractCreationCode,
18
+ })
19
+ return decodeAbiParameters(parseAbiParameters(batchTokenData.outputTypeHr || []) as any, returnedData.data)
20
+ }),
21
+ )
22
+
23
+ return decodedPromise.flatMap((d) => (d.status === 'fulfilled' ? d.value : [])).flat()
24
+ }
25
+
26
+ export const rpcFetchTokensData = async (chainId: number, rpc: string, tokensToFetch: string[]) => {
27
+ if (tokensToFetch.length > 0) {
28
+ const tokensChunks = chunk(tokensToFetch, 40)
29
+
30
+ const tokensCalls = tokensChunks.map((chunk) => {
31
+ const inputData = encodeAbiParameters(parseAbiParameters(batchTokenData.inputType) as any, [chunk])
32
+ return concatBytecode(batchTokenData.bytecode, inputData)
33
+ })
34
+
35
+ return await batchJsonRpc({
36
+ rpc,
37
+ calls: tokensCalls,
38
+ outputTypeAbi: batchTokenData.outputTypeHr,
39
+ callsKey: `tokens.ts: rpcFetchTokensData - chainId ${chainId} - rpc ${rpc}`,
40
+ })
41
+ }
42
+
43
+ return []
44
+ }
package/src/utils.ts CHANGED
@@ -2,7 +2,15 @@ import { tokens } from '@stake-dao/constants'
2
2
  import type { Token } from '@stake-dao/constants'
3
3
  import { request } from 'graphql-request'
4
4
  import { groupBy } from 'lodash-es'
5
- import { http, createPublicClient, decodeAbiParameters, extractChain, parseAbiParameters, toHex } from 'viem'
5
+ import {
6
+ http,
7
+ type Address,
8
+ createPublicClient,
9
+ decodeAbiParameters,
10
+ extractChain,
11
+ parseAbiParameters,
12
+ toHex,
13
+ } from 'viem'
6
14
  import * as viemChains from 'viem/chains'
7
15
  import { withTwoDec } from './number.js'
8
16
 
@@ -124,37 +132,41 @@ export interface BatchJsonRpcArgs {
124
132
  export const batchJsonRpc = async (args: BatchJsonRpcArgs) => {
125
133
  const { rpc, calls, outputTypeAbi, parse = true, callsKey } = args
126
134
 
127
- const rpcRequests = await (
128
- await fetch(rpc, {
129
- method: 'POST',
130
- headers: { 'Content-Type': 'application/json' },
131
- body: JSON.stringify(
132
- calls.map((calldata, index) => ({
133
- id: index,
134
- jsonrpc: '2.0',
135
- method: 'eth_call',
136
- params: [{ data: calldata }, 'latest'],
137
- })),
138
- ),
139
- })
140
- ).json()
135
+ if (calls.length > 0) {
136
+ const rpcRequests = await (
137
+ await fetch(rpc, {
138
+ method: 'POST',
139
+ headers: { 'Content-Type': 'application/json' },
140
+ body: JSON.stringify(
141
+ calls.map((calldata, index) => ({
142
+ id: index,
143
+ jsonrpc: '2.0',
144
+ method: 'eth_call',
145
+ params: [{ data: calldata }, 'latest'],
146
+ })),
147
+ ),
148
+ })
149
+ ).json()
141
150
 
142
- const rpcResults = rpcRequests.map((res: any, index: number) => {
143
- const isError = Object.keys(res).includes('error')
144
- const abi = Array.isArray(outputTypeAbi[0]) ? outputTypeAbi[index] : outputTypeAbi
145
- const status = isError ? 'error' : 'fulfilled'
146
- const value = isError
147
- ? `${callsKey} call index ${index}: code ${res.error.code}\n${res.error.message}`
148
- : decodeAbiParameters(parse ? (parseAbiParameters(abi) as any) : abi, res.result)
151
+ const rpcResults = rpcRequests.map((res: any, index: number) => {
152
+ const isError = Object.keys(res).includes('error')
153
+ const abi = Array.isArray(outputTypeAbi[0]) ? outputTypeAbi[index] : outputTypeAbi
154
+ const status = isError ? 'error' : 'fulfilled'
155
+ const value = isError
156
+ ? `${callsKey} call index ${index}: code ${res.error.code}\n${res.error.message}`
157
+ : decodeAbiParameters(parse ? (parseAbiParameters(abi) as any) : abi, res.result)
149
158
 
150
- if (isError) {
151
- console.error(value)
152
- }
159
+ if (isError) {
160
+ console.error(value)
161
+ }
153
162
 
154
- return { status, value }
155
- })
163
+ return { status, value }
164
+ })
165
+
166
+ return rpcResults.flatMap((r) => (r.status === 'fulfilled' ? r.value[0] : []))
167
+ }
156
168
 
157
- return rpcResults.flatMap((r) => (r.status === 'fulfilled' ? r.value[0] : []))
169
+ return []
158
170
  }
159
171
 
160
172
  interface BatchJsonRpcWithBlocksArgs {
@@ -210,7 +222,7 @@ export interface Call {
210
222
 
211
223
  export const multicall = async (provider: any, calls: Call[], abi: readonly any[]) => {
212
224
  const contracts = calls.map((c) => ({
213
- address: c.address as `0x${string}`,
225
+ address: c.address as Address,
214
226
  abi,
215
227
  functionName: c.name,
216
228
  args: c.params ? c.params : [],
@@ -1,7 +1,18 @@
1
1
  import { lc } from '../../utils.js'
2
2
 
3
3
  export const GAUGES_CHUNK_SIZE = 30
4
- export const GAUGES_METADATA_CHUNK_SIZE = 10
4
+ export const GAUGES_METADATA_CHUNK_SIZE = {
5
+ 1: 10,
6
+ 10: 10,
7
+ 100: 10,
8
+ 137: 10,
9
+ 250: 10,
10
+ 252: 10,
11
+ 8453: 10,
12
+ 42161: 10,
13
+ 42220: 10,
14
+ 43114: 10,
15
+ }
5
16
 
6
17
  export const NOT_LP_GAUGES = {
7
18
  42: '0xb9C05B8EE41FDCbd9956114B3aF15834FDEDCb54',
@@ -61,6 +61,7 @@ export const fetchCurveGauges = async (rpc: Rpcs): Promise<GaugesData> => {
61
61
 
62
62
  const gauges = rawGauges.map((g) => ({
63
63
  gauge: g.gauge,
64
+ childGauge: g.childGauge,
64
65
  weight: formatUnits(g.weight, 0),
65
66
  relativeWeight: formatUnits(g.relativeWeight, 0),
66
67
  futureRelativeWeight: formatUnits(g.futureRelativeWeight, 0),
@@ -76,10 +77,10 @@ export const fetchCurveGauges = async (rpc: Rpcs): Promise<GaugesData> => {
76
77
 
77
78
  for (const chainId of Object.keys(gaugesPerChain)) {
78
79
  const chainGauges = gaugesPerChain[chainId]!
79
- const chunkedChainGauges = chunk(chainGauges, GAUGES_METADATA_CHUNK_SIZE)
80
+ const chunkedChainGauges = chunk(chainGauges, GAUGES_METADATA_CHUNK_SIZE[chainId])
80
81
 
81
82
  const gaugesMetadataCalls = chunkedChainGauges.map((gaugeObj) => {
82
- const inputParams = [gaugeObj.map((g) => g.gauge)]
83
+ const inputParams = [gaugeObj.map((g) => g.childGauge)]
83
84
 
84
85
  const inputData = encodeAbiParameters(
85
86
  parseAbiParameters(batchCurveGaugesMetadata.inputType[0]!) as any,
@@ -107,7 +108,7 @@ export const fetchCurveGauges = async (rpc: Rpcs): Promise<GaugesData> => {
107
108
  const gaugesLpWithMissingCoins: string[] = []
108
109
 
109
110
  const parsedGauges = filteredGauges.map((g) => {
110
- const gaugeMetadata = gaugesMetadata.find((gm) => equalTlc(gm.gauge, g.gauge))
111
+ const gaugeMetadata = gaugesMetadata.find((gm) => equalTlc(gm.gauge, g.childGauge))
111
112
  const filteredCoins = gaugeMetadata.coins.filter((c) => c._address !== zeroAddress)
112
113
 
113
114
  const name = gaugeMetadata.lp.name
@@ -123,6 +124,7 @@ export const fetchCurveGauges = async (rpc: Rpcs): Promise<GaugesData> => {
123
124
 
124
125
  return {
125
126
  gauge: g.gauge,
127
+ childGauge: g.childGauge,
126
128
  manager: gaugeMetadata.manager,
127
129
  name,
128
130
  weight: g.weight,
@@ -28,7 +28,7 @@ export const fetchCurveUserVotes = async (rpc: string, user: string): Promise<Ga
28
28
  calls,
29
29
  outputTypeAbi: batchCurveUserVotes.outputType![mainnet.id],
30
30
  parse: false,
31
- callsKey: `votemarket/curve/fetchCurveUserVotes.ts: rawGauges - chainId ${mainnet.id} - rpc ${rpc[mainnet.id]}`,
31
+ callsKey: `votemarket/curve/fetchCurveUserVotes.ts: rawGauges - chainId ${mainnet.id} - rpc ${rpc}`,
32
32
  })
33
33
 
34
34
  const veBalance = rawVotes[0].veBalance
@@ -0,0 +1,132 @@
1
+ import { ONE_WEEK, Zero, contract, tokenWithAddress } from '@stake-dao/constants'
2
+ import { type Address, formatUnits, parseAbi } from 'viem'
3
+ import { mainnet } from 'viem/chains'
4
+ import { GH_STAKE_DAO_BOUNTIES_REPORT } from '../../endpoints.js'
5
+ import { type Price, getPrices } from '../../prices.js'
6
+ import { rpcFetchTokensData } from '../../tokens.js'
7
+ import { equalTlc, multicall } from '../../utils.js'
8
+
9
+ type Rpcs = {
10
+ [chainId: number]: string
11
+ }
12
+
13
+ type UnknownToken = {
14
+ name: string
15
+ symbol: string
16
+ address: string
17
+ decimals: number
18
+ chainId: number
19
+ }
20
+
21
+ const getMerkleData = async (epoch: number) => {
22
+ return await fetch(
23
+ `${GH_STAKE_DAO_BOUNTIES_REPORT}/refs/heads/main/bounties-reports/${epoch}/vlCVX/merkle_data.json`,
24
+ ).then((res) => res.json())
25
+ }
26
+
27
+ const getClaimedData = async (provider: any, tokens: string[], user: string, contract: string) => {
28
+ const rawClaimed =
29
+ tokens.length > 0
30
+ ? await multicall(
31
+ provider,
32
+ tokens.map((t) => ({
33
+ address: contract,
34
+ name: 'claimed',
35
+ params: [user, t],
36
+ })),
37
+ parseAbi(['function claimed(address,address) external view returns (uint256)']),
38
+ )
39
+ : []
40
+
41
+ return tokens.map((t, index) => ({
42
+ token: t,
43
+ claimed: rawClaimed[index].result,
44
+ }))
45
+ }
46
+
47
+ const getParsedData = (
48
+ merkleAddress: string,
49
+ userData: any,
50
+ unknownTokensData: any[],
51
+ claimedData: any[],
52
+ prices: Price[],
53
+ ) => {
54
+ return userData
55
+ ? Object.keys(userData.tokens).map((token) => {
56
+ const rewardToken = tokenWithAddress(token) || unknownTokensData.find((t) => equalTlc(t.address, token))
57
+ const tokenPrice = prices.find((p) => equalTlc(token, p.address))?.usdPrice || 0
58
+
59
+ const claimed = claimedData.find((c) => equalTlc(c.token, token))?.claimed
60
+ const claimable = BigInt(userData.tokens[token].amount) - claimed
61
+
62
+ return {
63
+ token: rewardToken,
64
+ claimable: formatUnits(claimable, 0),
65
+ claimableUsd: Number(formatUnits(claimable, rewardToken?.decimals || 18)) * tokenPrice,
66
+ amount: userData.tokens[token].amount,
67
+ amountUsd:
68
+ Number(formatUnits(BigInt(userData.tokens[token].amount), rewardToken?.decimals || 18)) * tokenPrice,
69
+ proof: userData.tokens[token].proof,
70
+ merkleAddress: merkleAddress as Address,
71
+ isClaimed: claimable === Zero,
72
+ }
73
+ })
74
+ : undefined
75
+ }
76
+
77
+ export const fetchUserVlCvxClaimable = async (provider: any, rpc: Rpcs, user: string) => {
78
+ const nowEpoch = Math.floor(Date.now() / (1000 * ONE_WEEK)) * ONE_WEEK
79
+
80
+ let vlCvxClaimable: any
81
+ try {
82
+ vlCvxClaimable = await getMerkleData(nowEpoch)
83
+ } catch {
84
+ vlCvxClaimable = await getMerkleData(nowEpoch - ONE_WEEK)
85
+ }
86
+
87
+ const vlCvxUserDelegated = vlCvxClaimable?.delegators.claims[user]
88
+ const vlCvxUserNotDelegated = vlCvxClaimable?.nonDelegators.claims[user]
89
+
90
+ const tokensDelegated = Object.keys(vlCvxUserDelegated?.tokens || {})
91
+ const tokensNotDelegated = Object.keys(vlCvxUserNotDelegated?.tokens || {})
92
+
93
+ const tokens = [...tokensDelegated, ...tokensNotDelegated]
94
+
95
+ if (!tokens.length) return []
96
+
97
+ const [delegatedClaimed, notDelegatedClaimed] = await Promise.all([
98
+ getClaimedData(provider, tokensDelegated, user, contract('vlCvxDelegatorMerkle', mainnet.id)),
99
+ getClaimedData(provider, tokensNotDelegated, user, contract('vlCvxNotDelegatorMerkle', mainnet.id)),
100
+ ])
101
+
102
+ const unknownTokens = tokens.filter((t) => !tokenWithAddress(t))
103
+ const rawUnknownTokensData = await rpcFetchTokensData(mainnet.id, rpc[mainnet.id]!, unknownTokens)
104
+ const unknownTokensData: UnknownToken[] = rawUnknownTokensData.map((t) => ({
105
+ name: t.name,
106
+ symbol: t.symbol,
107
+ address: t.tokenAddress,
108
+ decimals: Number(t.decimals),
109
+ chainId: mainnet.id,
110
+ }))
111
+
112
+ const prices = await getPrices(tokens.map((t) => ({ address: t })) as any[], mainnet.id)
113
+
114
+ return [
115
+ getParsedData(
116
+ contract('vlCvxDelegatorMerkle', mainnet.id),
117
+ vlCvxUserDelegated,
118
+ unknownTokensData,
119
+ delegatedClaimed,
120
+ prices,
121
+ ),
122
+ getParsedData(
123
+ contract('vlCvxNotDelegatorMerkle', mainnet.id),
124
+ vlCvxUserNotDelegated,
125
+ unknownTokensData,
126
+ notDelegatedClaimed,
127
+ prices,
128
+ ),
129
+ ]
130
+ .filter(Boolean)
131
+ .flat()
132
+ }
@@ -1,12 +1,11 @@
1
- import { ONE_WEEK, RPC, contracts, tokenWithAddress, tokens } from '@stake-dao/constants'
2
- import { chunk, filter, range, remove, uniq } from 'lodash-es'
1
+ import { ONE_WEEK, RPC, Zero, contract, contracts, tokenWithAddress, tokens } from '@stake-dao/constants'
2
+ import { filter, range, remove, uniq } from 'lodash-es'
3
3
  import { decodeAbiParameters, encodeAbiParameters, formatUnits, parseAbiParameters, zeroAddress } from 'viem'
4
4
  import { mainnet } from 'viem/chains'
5
- import { batchTokenData } from '../bytecodes/index.js'
6
5
  import batchCampaigns from '../bytecodes/votemarket/batchCampaigns.js'
7
6
  import batchGaugesWeight from '../bytecodes/votemarket/batchGaugesWeight.js'
8
7
  import { getPrices } from '../prices.js'
9
- import { Zero } from '../strategies/utils/index.js'
8
+ import { rpcFetchTokensData } from '../tokens.js'
10
9
  import { batchJsonRpc, concatBytecode, equalTlc, rpcCall, rpcGetLastBlockTimetstamp } from '../utils.js'
11
10
  import type { Campaign, RawCampaign, RawPeriod } from './types.js'
12
11
 
@@ -17,7 +16,7 @@ export const CLOSE_WINDOW_LENGTH = 4 // weeks
17
16
  interface FetchCampaignsProps {
18
17
  platform: string
19
18
  chainId: number
20
- rpc: string
19
+ rpcs: { [chainId: number]: string }
21
20
  }
22
21
 
23
22
  const updateEpoch = ({
@@ -80,7 +79,9 @@ const updateEpoch = ({
80
79
  return campaign
81
80
  }
82
81
 
83
- export const fetchCampaigns = async ({ platform, chainId, rpc }: FetchCampaignsProps): Promise<Campaign[]> => {
82
+ export const fetchCampaigns = async ({ platform, chainId, rpcs }: FetchCampaignsProps): Promise<Campaign[]> => {
83
+ const rpc = rpcs[chainId]!
84
+
84
85
  const block = await rpcGetLastBlockTimetstamp(rpc)
85
86
  const nCampaignsRequest = await rpcCall(rpc, [{ to: platform, data: '0x7274e30d' }]) // campaignCount
86
87
  const nCampaigns = Number(
@@ -89,7 +90,9 @@ export const fetchCampaigns = async ({ platform, chainId, rpc }: FetchCampaignsP
89
90
 
90
91
  const calls = range(0, nCampaigns, CAMPAIGNS_CHUNK_SIZE).map((skip) => {
91
92
  const inputParams = [
93
+ chainId,
92
94
  platform,
95
+ contract('laPosteTokenFactory', chainId),
93
96
  skip,
94
97
  skip + CAMPAIGNS_CHUNK_SIZE > nCampaigns ? nCampaigns : skip + CAMPAIGNS_CHUNK_SIZE,
95
98
  ]
@@ -124,23 +127,7 @@ export const fetchCampaigns = async ({ platform, chainId, rpc }: FetchCampaignsP
124
127
 
125
128
  const campaignsTokens: string[] = uniq(rawCampaigns.map((rc) => rc.campaign.rewardToken))
126
129
  const tokensToFetch: string[] = remove(campaignsTokens, (t) => !tokenWithAddress(t, chainId))
127
-
128
- let rawTokensData: any[] = []
129
- if (tokensToFetch.length > 0) {
130
- const tokensChunks = chunk(tokensToFetch, 40)
131
-
132
- const tokensCalls = tokensChunks.map((chunk) => {
133
- const inputData = encodeAbiParameters(parseAbiParameters(batchTokenData.inputType) as any, [chunk])
134
- return concatBytecode(batchTokenData.bytecode, inputData)
135
- })
136
-
137
- rawTokensData = await batchJsonRpc({
138
- rpc,
139
- calls: tokensCalls,
140
- outputTypeAbi: batchTokenData.outputTypeHr,
141
- callsKey: `votemarket/fetchCampaigns.ts: rawTokensData - chainId ${chainId} - rpc ${rpc}`,
142
- })
143
- }
130
+ const rawTokensData: any[] = tokensToFetch.length > 0 ? await rpcFetchTokensData(chainId, rpc, tokensToFetch) : []
144
131
 
145
132
  const fetchedTokens: any = [
146
133
  ...filter(tokens, (t) => campaignsTokens.find((ct) => equalTlc(ct, t.address))),
@@ -153,21 +140,55 @@ export const fetchCampaigns = async ({ platform, chainId, rpc }: FetchCampaignsP
153
140
  })),
154
141
  ]
155
142
 
156
- // const prices = await getPrices(fetchedTokens as any, chainId)
157
- // TMP FOR TEST PURPOSE REMOVE ONCE IN PROD
143
+ const campaignsNativeTokens: string[] = uniq(
144
+ rawCampaigns.filter((rc) => Number(rc.rewardChainId) === mainnet.id).map((rc) => rc.rewardAddress),
145
+ )
146
+ const nativeTokensToFetch: string[] = remove(campaignsNativeTokens, (t) => !tokenWithAddress(t, mainnet.id))
147
+ const rawNativeTokensData: any[] =
148
+ nativeTokensToFetch.length > 0 ? await rpcFetchTokensData(mainnet.id, rpcs[mainnet.id]!, nativeTokensToFetch) : []
149
+
150
+ const nativeFetchedTokens: any = [
151
+ ...filter(tokens, (t) => campaignsNativeTokens.find((ct) => equalTlc(ct, t.address))),
152
+ ...rawNativeTokensData.map((t) => ({
153
+ name: t.name,
154
+ symbol: t.symbol,
155
+ address: t.tokenAddress,
156
+ decimals: Number(t.decimals),
157
+ chainId: mainnet.id,
158
+ })),
159
+ ]
160
+
158
161
  const prices = [
159
- ...(await getPrices(fetchedTokens as any, chainId)),
160
- { address: '0x9E49A0314AE61e9C9E34e4Af62a73FBFfB6DE95A', symbol: 'ARR', usdPrice: 10 },
162
+ ...(fetchedTokens.length > 0 ? await getPrices(fetchedTokens as any, chainId) : []),
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
161
168
  ]
162
169
 
170
+ const allFetchedTokens = [...fetchedTokens, ...nativeFetchedTokens]
171
+
163
172
  const currentTimestamp = block.timestamp
164
173
 
165
174
  const campaigns = rawCampaigns.map((rc) => {
166
175
  const gaugeWeightData = rawGaugesWeights.find((g) => equalTlc(g.gauge, rc.campaign.gauge))
167
- const rewardToken = fetchedTokens.find((t) => equalTlc(t.address, rc.campaign.rewardToken) && t.chainId === chainId)
176
+
177
+ let receiptRewardToken = undefined
178
+ let rewardToken = allFetchedTokens.find(
179
+ (t) => equalTlc(t.address, rc.campaign.rewardToken) && t.chainId === chainId,
180
+ )
181
+
182
+ if (!equalTlc(rewardToken.address, rc.rewardAddress)) {
183
+ receiptRewardToken = rewardToken
184
+ rewardToken = allFetchedTokens.find(
185
+ (t) => equalTlc(t.address, rc.rewardAddress) && t.chainId === Number(rc.rewardChainId),
186
+ )
187
+ }
188
+
168
189
  const decimals = rewardToken ? rewardToken.decimals : 18
169
190
 
170
- const rewardTokenPrice = prices.find((p) => equalTlc(rc.campaign.rewardToken, p.address))?.usdPrice || 0
191
+ const rewardTokenPrice = prices.find((p) => equalTlc(rc.rewardAddress, p.address))?.usdPrice || 0
171
192
 
172
193
  const startTimestamp = Number(rc.campaign.startTimestamp)
173
194
  const endTimestamp = Number(rc.campaign.endTimestamp)
@@ -194,31 +215,14 @@ export const fetchCampaigns = async ({ platform, chainId, rpc }: FetchCampaignsP
194
215
  const rawCurrentPeriod = rc.periods[indexOfCurrentPeriod]
195
216
  const rawPreviousPeriod = rc.periods[indexOfCurrentPeriod - 1]
196
217
 
197
- // // Simulate previous period update if not updated
198
- // if (rc.previousPeriod && !rc.previousPeriod.updated && Number(numberOfPeriods) > Number(rc.periodLeft)) {
199
- // updateEpoch({
200
- // period: rc.previousPeriod,
201
- // campaign: rc.campaign,
202
- // remainingPeriods: Number(rc.periodLeft) + 1,
203
- // totalVotes,
204
- // })
205
- // }
206
-
207
- // // Simulate current period update to simulate reward and apr
208
- // updateEpoch({
209
- // period: rc.currentPeriod,
210
- // previousPeriod: rc.previousPeriod,
211
- // campaign: rc.campaign,
212
- // remainingPeriods: Number(rc.periodLeft),
213
- // totalVotes,
214
- // })
215
-
216
218
  return {
217
219
  id: Number(rc.id),
218
220
  chainId,
219
- gauge: rc.campaign.gauge,
221
+ rewardChainId: Number(rc.rewardChainId),
220
222
  gaugeChainId: Number(rc.campaign.chainId),
223
+ gauge: rc.campaign.gauge,
221
224
  manager: rc.campaign.manager,
225
+ receiptRewardToken,
222
226
  rewardToken,
223
227
  rewardTokenPrice,
224
228
  numberOfPeriods,
@@ -233,12 +237,14 @@ export const fetchCampaigns = async ({ platform, chainId, rpc }: FetchCampaignsP
233
237
  addresses: rc.addresses,
234
238
  isWhitelist: rc.isWhitelistOnly,
235
239
  isBlacklist: !rc.isWhitelistOnly && rc.addresses.length > 0,
236
- previousPeriod: {
237
- rewardPerPeriod: formatUnits(rawPreviousPeriod.rewardPerPeriod, decimals),
238
- rewardPerVote: formatUnits(rawPreviousPeriod.rewardPerVote, decimals),
239
- leftover: formatUnits(rawPreviousPeriod.leftover, decimals),
240
- updated: rawPreviousPeriod.updated,
241
- },
240
+ previousPeriod: rawPreviousPeriod
241
+ ? {
242
+ rewardPerPeriod: formatUnits(rawPreviousPeriod.rewardPerPeriod, decimals),
243
+ rewardPerVote: formatUnits(rawPreviousPeriod.rewardPerVote, decimals),
244
+ leftover: formatUnits(rawPreviousPeriod.leftover, decimals),
245
+ updated: rawPreviousPeriod.updated,
246
+ }
247
+ : undefined,
242
248
  currentPeriod: {
243
249
  rewardPerPeriod: formatUnits(rawCurrentPeriod.rewardPerPeriod, decimals),
244
250
  rewardPerVote: formatUnits(rawCurrentPeriod.rewardPerVote, decimals),
@@ -1,18 +1,15 @@
1
- import { arbitrum } from '@stake-dao/constants'
2
1
  import { chunk } from 'lodash-es'
3
2
  import { encodeAbiParameters, formatUnits, parseAbiParameters } from 'viem'
3
+ import { arbitrum } from 'viem/chains'
4
4
  import batchClaimableData from '../bytecodes/votemarket/batchClaimableData.js'
5
5
  import { concatBytecode } from '../index.js'
6
6
  import { batchJsonRpc } from '../utils.js'
7
7
 
8
- type Rpcs = {
9
- [chainId: number]: string
10
- }
11
-
12
8
  const CLAIMABLE_CHUNK_SIZE = 10
13
9
 
14
10
  export const fetchClaimableData = async (
15
- rpc: Rpcs,
11
+ chainId: number,
12
+ rpc: string,
16
13
  platform: string,
17
14
  user: string,
18
15
  campaigns: number[],
@@ -22,20 +19,18 @@ export const fetchClaimableData = async (
22
19
  const inputVotesChunks = chunk(userVotes, CLAIMABLE_CHUNK_SIZE)
23
20
 
24
21
  const claimableCalls = inputCampaignsChunks.map((campaignsArgs, index) => {
25
- const inputData = encodeAbiParameters(parseAbiParameters(batchClaimableData.inputType[arbitrum.id]!) as any, [
26
- platform,
27
- user,
28
- campaignsArgs,
29
- inputVotesChunks[index],
30
- ])
31
- return concatBytecode(batchClaimableData.bytecode[arbitrum.id]!, inputData)
22
+ const inputData = encodeAbiParameters(
23
+ parseAbiParameters(batchClaimableData.inputType[chainId] || batchClaimableData.inputType[arbitrum.id]!) as any,
24
+ [platform, user, campaignsArgs, inputVotesChunks[index]],
25
+ )
26
+ return concatBytecode(batchClaimableData.bytecode[chainId] || batchClaimableData.bytecode[arbitrum.id]!, inputData)
32
27
  })
33
28
 
34
29
  const claimable = await batchJsonRpc({
35
- rpc: rpc[arbitrum.id]!,
30
+ rpc,
36
31
  calls: claimableCalls,
37
- outputTypeAbi: batchClaimableData.outputTypeHr[arbitrum.id],
38
- callsKey: `Batch claimable data - chainId ${arbitrum.id} - rpc ${rpc[arbitrum.id]}`,
32
+ outputTypeAbi: batchClaimableData.outputTypeHr[chainId] || batchClaimableData.outputTypeHr[arbitrum.id]!,
33
+ callsKey: `Batch claimable data - chainId ${chainId} - rpc ${rpc}`,
39
34
  })
40
35
 
41
36
  return claimable.map((c) => ({
@@ -1,3 +1,4 @@
1
+ import { Zero } from '@stake-dao/constants'
1
2
  import { http, createPublicClient, toHex, toRlp } from 'viem'
2
3
  import { mainnet } from 'viem/chains'
3
4
  import { BLOCK_HEADER } from './config.js'
@@ -10,7 +11,7 @@ type Rpcs = {
10
11
  function encodeRlpBlock(block: Record<string, any>): string {
11
12
  const blockHeader = BLOCK_HEADER.map((key) => {
12
13
  if (key in block) {
13
- if (typeof block[key] === 'bigint' && block[key] === BigInt(0)) {
14
+ if (typeof block[key] === 'bigint' && block[key] === Zero) {
14
15
  return '0x'
15
16
  }
16
17
  if (typeof block[key] === 'string') {