diff --git a/.env.example b/.env.example index 8487584..6e60c0a 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,10 @@ DISCORD_TOKEN= -JSON_RPC_URL= +MAINNET_JSON_RPC_URL= +OPTIMISM_JSON_RPC_URL= +POLYGON_JSON_RPC_URL= +ARBITRUM_JSON_RPC_URL= +POLYGON_ZKEVM_JSON_RPC_URL= +SUBGRAPH_APIKEY= # Twitter TWITTER_API_KEY= diff --git a/src/config/etherProvider.ts b/src/config/etherProvider.ts index e514bfe..a8fda96 100644 --- a/src/config/etherProvider.ts +++ b/src/config/etherProvider.ts @@ -1,6 +1,13 @@ import { ethers } from 'ethers'; import 'dotenv/config'; +import { ChainIds } from '../globals/chainIds'; -const provider = new ethers.JsonRpcProvider(process.env.JSON_RPC_URL); +const provider = { + [ChainIds.POLYGON_ZKEVM]: new ethers.JsonRpcProvider(process.env.POLYGON_ZKEVM_JSON_RPC_URL), + [ChainIds.MAINNET]: new ethers.JsonRpcProvider(process.env.MAINNET_JSON_RPC_URL), + [ChainIds.ARBITRUM]: new ethers.JsonRpcProvider(process.env.ARBITRUM_JSON_RPC_URL), + [ChainIds.OPTIMISM]: new ethers.JsonRpcProvider(process.env.OPTIMISM_JSON_RPC_URL), + [ChainIds.POLYGON]: new ethers.JsonRpcProvider(process.env.POLYGON_JSON_RPC_URL), +}; export default provider; diff --git a/src/data/abi/ERC20.json b/src/data/abi/ERC20.json index 7f28a6f..86cfcbd 100644 --- a/src/data/abi/ERC20.json +++ b/src/data/abi/ERC20.json @@ -1,43 +1,43 @@ [ - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } -] \ No newline at end of file + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/src/data/abi/FxGauge.json b/src/data/abi/FxGauge.json index 4ede8c1..433ef5b 100644 --- a/src/data/abi/FxGauge.json +++ b/src/data/abi/FxGauge.json @@ -1,22 +1,22 @@ [ - { - "inputs": [], - "name": "stakingToken", - "outputs":[{"internalType":"address","name":"","type":"address"}], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } -] \ No newline at end of file + { + "inputs": [], + "name": "stakingToken", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/src/data/abi/QuestBoardAbi.json b/src/data/abi/QuestBoardAbi.json index d86200d..2028795 100644 --- a/src/data/abi/QuestBoardAbi.json +++ b/src/data/abi/QuestBoardAbi.json @@ -1,125 +1,166 @@ [ - { - "anonymous": false, - "inputs": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "questID", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "gauge", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint48", + "name": "duration", + "type": "uint48" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startPeriod", + "type": "uint256" + } + ], + "name": "NewQuest", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "questId", + "type": "uint256" + } + ], + "name": "getAllQuestPeriodsForQuestId", + "outputs": [ + { + "components": [ { - "indexed": true, "internalType": "uint256", - "name": "questID", + "name": "rewardAmountPerPeriod", "type": "uint256" }, { - "indexed": true, - "internalType": "address", - "name": "creator", - "type": "address" + "internalType": "uint256", + "name": "minRewardPerVote", + "type": "uint256" }, { - "indexed": true, - "internalType": "address", - "name": "gauge", - "type": "address" + "internalType": "uint256", + "name": "maxRewardPerVote", + "type": "uint256" }, { - "indexed": false, - "internalType": "address", - "name": "rewardToken", - "type": "address" + "internalType": "uint256", + "name": "minObjectiveVotes", + "type": "uint256" }, { - "indexed": false, - "internalType": "uint48", - "name": "duration", - "type": "uint48" + "internalType": "uint256", + "name": "maxObjectiveVotes", + "type": "uint256" }, { - "indexed": false, "internalType": "uint256", - "name": "startPeriod", + "name": "rewardAmountDistributed", "type": "uint256" + }, + { + "internalType": "uint48", + "name": "periodStart", + "type": "uint48" + }, + { + "internalType": "enum QuestDataTypes.PeriodState", + "name": "currentState", + "type": "uint8" + } + ], + "internalType": "struct IQuestBoard.QuestPeriod[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "period", + "type": "uint256" + } + ], + "name": "getQuestIdsForPeriod", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "name": "quests", + "outputs": [ + { "internalType": "address", "name": "creator", "type": "address" }, + { "internalType": "address", "name": "rewardToken", "type": "address" }, + { "internalType": "address", "name": "gauge", "type": "address" }, + { "internalType": "uint48", "name": "duration", "type": "uint48" }, + { "internalType": "uint48", "name": "periodStart", "type": "uint48" }, + { "internalType": "uint256", "name": "totalRewardAmount", "type": "uint256" }, + { "internalType": "uint256", "name": "rewardAmountPerPeriod", "type": "uint256" }, + { "internalType": "uint256", "name": "minRewardPerVote", "type": "uint256" }, + { "internalType": "uint256", "name": "maxRewardPerVote", "type": "uint256" }, + { "internalType": "uint256", "name": "minObjectiveVotes", "type": "uint256" }, + { "internalType": "uint256", "name": "maxObjectiveVotes", "type": "uint256" }, + { + "components": [ + { + "internalType": "enum QuestDataTypes.QuestVoteType", + "name": "voteType", + "type": "uint8" + }, + { + "internalType": "enum QuestDataTypes.QuestRewardsType", + "name": "rewardsType", + "type": "uint8" + }, + { + "internalType": "enum QuestDataTypes.QuestCloseType", + "name": "closeType", + "type": "uint8" } ], - "name": "NewQuest", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "questId", - "type": "uint256" - } - ], - "name": "getAllQuestPeriodsForQuestId", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "rewardAmountPerPeriod", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "minRewardPerVote", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxRewardPerVote", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "minObjectiveVotes", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxObjectiveVotes", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "rewardAmountDistributed", - "type": "uint256" - }, - { - "internalType": "uint48", - "name": "periodStart", - "type": "uint48" - }, - { - "internalType": "enum QuestDataTypes.PeriodState", - "name": "currentState", - "type": "uint8" - } - ], - "internalType": "struct IQuestBoard.QuestPeriod[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "period", - "type": "uint256" - } - ], - "name": "getQuestIdsForPeriod", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - } -] \ No newline at end of file + "internalType": "struct IQuestBoard.QuestTypes", + "name": "types", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/src/data/data.json b/src/data/data.json index fd5321a..586b36f 100644 --- a/src/data/data.json +++ b/src/data/data.json @@ -3,8 +3,26 @@ "curveTargetChannelIds": ["1008049103793561670"], "balancerTargetChannelIds": ["1008049911624913018", "999427452789067926"], "fxTargetChannelIds": ["1218099479803199490"], - "veCRVQuestBoardContractAddresses": ["0xF13e938d7a1214ae438761941BC0C651405e68A4"], - "veBALQuestBoardContractAddresses": ["0xf0CeABf99Ddd591BbCC962596B228007eD4624Ae"], - "veLITQuestBoardContractAddresses": ["0x1B921DBD13A280ee14BA6361c1196EB72aaa094e"], - "veFXNQuestBoardContractAddresses": ["0xeB9C1Dbd95dcF5190E6D31Ba94f89593D48990bE"] + "veCRVQuestBoardContractAddresses": { + "1": ["0xAa1698f0A51e6d00F5533cc3E5D36010ee4558C6"], + "42161": ["0x2Aa638596429e4734D872feC6e7a42e3f3D9fBf8"], + "137": ["0x089154A7E4C562d5998AB3D7Ca57B504A8912482"] + }, + "veBALQuestBoardContractAddresses": { + "1": [ + "0xfEb352930cA196a80B708CDD5dcb4eCA94805daB", + "0xfd9F19A9B91BecAE3c8dABC36CDd1eA86Fc1A222" + ], + "42161": ["0x8EdcFE9Bc7d2a735117B94C16456D8303777abbb"], + "10": ["0x12Da7E0c469CEeC4EFADa2F5E8CAedCD3F3E6748"], + "137": ["0x0482A2d6e2F895125b7237de70c675cd55FE17Ca"], + "1101": ["0x2Aa638596429e4734D872feC6e7a42e3f3D9fBf8"] + }, + "veLITQuestBoardContractAddresses": { + "1": ["0xDD3cbe4E0f10910eb435EA6DBe97469ABc3d7e9c"], + "42161": ["0x04C70Abaa9D3eB14F090094eDc72D5581Dc65A22"] + }, + "veFXNQuestBoardContractAddresses": { + "1": ["0x59AbF8642f4c7D8d3C5633eDCBBf6B12234FF02D"] + } } diff --git a/src/globals/chainIds.ts b/src/globals/chainIds.ts new file mode 100644 index 0000000..ad799c9 --- /dev/null +++ b/src/globals/chainIds.ts @@ -0,0 +1,7 @@ +export enum ChainIds { + MAINNET = '1', + OPTIMISM = '10', + ARBITRUM = '42161', + POLYGON = '137', + POLYGON_ZKEVM = '1101', +} diff --git a/src/listener/ethers/questCreationListener.ts b/src/listener/ethers/questCreationListener.ts index c7e6688..80cec0d 100644 --- a/src/listener/ethers/questCreationListener.ts +++ b/src/listener/ethers/questCreationListener.ts @@ -16,6 +16,8 @@ import formatRewardPerVote from '../../scripts/formatRewardPerVote'; import { ProtocolType } from '../../type/protocolType'; import getQuestPeriod from '../../scripts/getQuestPeriods'; import { QuestType } from '../../type/questType'; +import { ChainIds } from '../../globals/chainIds'; +import { getQuest, RewardsType } from '../../scripts/getQuest'; const getChannels = (protocol: ProtocolType): string[] => { switch (protocol) { @@ -174,7 +176,7 @@ const getEmbedColor = (protocol: ProtocolType): number => { }; const questCreationListener = - (protocolType: ProtocolType, questBoardAddress: string): Listener => + (protocolType: ProtocolType, questBoardAddress: string, chainId: ChainIds): Listener => async ( questID: bigint, creator: string, @@ -185,20 +187,38 @@ const questCreationListener = ) => { console.log(`Quest ${questID} created by ${creator} on ${protocolType}`); try { - const periods = await getQuestPeriod(questBoardAddress, questID); - const latestPeriod = periods[periods.length - 1]; + let maxObjectiveVotes: bigint; + let maxRewardPerVote: bigint; + let minObjectiveVotes: bigint; + let minRewardPerVote: bigint; + let rewardAmountPerPeriod: bigint; + let questType: QuestType; + if (chainId === ChainIds.MAINNET) { + const quest = await getQuest(questBoardAddress, questID, chainId); - const maxObjectiveVotes = latestPeriod.maxObjectiveVotes; - const maxRewardPerVote = latestPeriod.maxRewardPerVote; - const minObjectiveVotes = latestPeriod.minObjectiveVotes; - const minRewardPerVote = latestPeriod.minRewardPerVote; - const rewardAmountPerPeriod = latestPeriod.rewardAmountPerPeriod; + maxObjectiveVotes = quest.maxObjectiveVotes; + maxRewardPerVote = quest.maxRewardPerVote; + minObjectiveVotes = quest.minObjectiveVotes; + minRewardPerVote = quest.minRewardPerVote; + rewardAmountPerPeriod = quest.rewardAmountPerPeriod; - const questType = minRewardPerVote == maxRewardPerVote ? QuestType.Fixe : QuestType.Range; + questType = quest.types.rewardsType == RewardsType.FIXED ? QuestType.Fixe : QuestType.Range; + } else { + const periods = await getQuestPeriod(questBoardAddress, questID, chainId); + const latestPeriod = periods[periods.length - 1]; + + maxObjectiveVotes = latestPeriod.maxObjectiveVotes; + maxRewardPerVote = latestPeriod.maxRewardPerVote; + minObjectiveVotes = latestPeriod.minObjectiveVotes; + minRewardPerVote = latestPeriod.minRewardPerVote; + rewardAmountPerPeriod = latestPeriod.rewardAmountPerPeriod; + + questType = minRewardPerVote == maxRewardPerVote ? QuestType.Fixe : QuestType.Range; + } - const gaugeSymbol = await getSymbolFromGauge(gauge, protocolType); - const rewardTokenSymbol = await getSymbolFromToken(rewardToken); - const rewardTokenDecimals = await getDecimalsFromToken(rewardToken); + const gaugeSymbol = await getSymbolFromGauge(gauge, protocolType, chainId); + const rewardTokenSymbol = await getSymbolFromToken(rewardToken, chainId); + const rewardTokenDecimals = await getDecimalsFromToken(rewardToken, chainId); const totalRewardToken = getTotalRewardToken( rewardAmountPerPeriod, duration, diff --git a/src/scripts/createEtherEventListener.ts b/src/scripts/createEtherEventListener.ts index 27d403c..abfec40 100644 --- a/src/scripts/createEtherEventListener.ts +++ b/src/scripts/createEtherEventListener.ts @@ -1,23 +1,26 @@ import { Contract, Listener } from 'ethers'; import provider from '../config/etherProvider'; import { ProtocolType } from '../type/protocolType'; +import { ChainIds } from '../globals/chainIds'; const createEtherEventListener = ( - addresses: string[], + addresses: { [key: string]: string[] }, abi: any, eventName: string, - listener: (protocolType: ProtocolType, questBoardAddress: string) => Listener, + listener: (protocolType: ProtocolType, questBoardAddress: string, chainId: ChainIds) => Listener, protocolType: ProtocolType, ) => { - addresses.forEach((address) => { - try { - const contract = new Contract(address, abi, provider); - contract.on(eventName, listener(protocolType, address)); - console.log(`Listening to ${address}`); - } catch (err) { - console.error(err); - } - }); + for (const chainId in addresses) { + addresses[chainId].forEach((address) => { + try { + const contract = new Contract(address, abi, provider[chainId as ChainIds]); + contract.on(eventName, listener(protocolType, address, chainId as ChainIds)); + console.log(`Listening to ${address}`); + } catch (err) { + console.error(err); + } + }); + } }; export default createEtherEventListener; diff --git a/src/scripts/getAvailableQuestsForPeriod.ts b/src/scripts/getAvailableQuestsForPeriod.ts index b9a2b1e..4f35895 100644 --- a/src/scripts/getAvailableQuestsForPeriod.ts +++ b/src/scripts/getAvailableQuestsForPeriod.ts @@ -2,24 +2,32 @@ import { Contract } from 'ethers'; import { WEEK } from '../globals/time'; import provider from '../config/etherProvider'; import QuestBoardAbi from '../data/abi/QuestBoardAbi.json'; +import { ChainIds } from '../globals/chainIds'; -const getAvailableQuestsForPeriod = async (addresses: string[]): Promise => { - let amount = 0n; - - await Promise.all( - addresses.map(async (address) => { - try { - const contract = new Contract(address, QuestBoardAbi, provider); - const availableQuestsNb = await contract.getQuestIdsForPeriod( - (BigInt(Date.now()) / 1000n / WEEK) * WEEK, - ); - amount = amount + BigInt(availableQuestsNb.length); - } catch (err) { - console.error(err); - } +const getAvailableQuestsForPeriod = async (addresses: { + [key: string]: string[]; +}): Promise => { + const amounts = await Promise.all( + Object.keys(addresses).map(async (chainId) => { + let amount = 0n; + await Promise.all( + addresses[chainId].map(async (address) => { + try { + const contract = new Contract(address, QuestBoardAbi, provider[chainId as ChainIds]); + const availableQuestsNb = await contract.getQuestIdsForPeriod( + (BigInt(Date.now()) / 1000n / WEEK) * WEEK, + ); + amount += BigInt(availableQuestsNb.length); + } catch (err) { + console.error(err); + } + }), + ); + return amount; }), ); - return amount; + + return amounts.reduce((a, b) => a + b, 0n); }; export default getAvailableQuestsForPeriod; diff --git a/src/scripts/getDecimalsFromToken.ts b/src/scripts/getDecimalsFromToken.ts index b669aa1..cac323e 100644 --- a/src/scripts/getDecimalsFromToken.ts +++ b/src/scripts/getDecimalsFromToken.ts @@ -1,10 +1,11 @@ import { Contract } from 'ethers'; import provider from '../config/etherProvider'; import ERC20 from '../data/abi/ERC20.json'; +import { ChainIds } from '../globals/chainIds'; -const getDecimalsFromToken = async (tokenAddress: string): Promise => { +const getDecimalsFromToken = async (tokenAddress: string, chainId: ChainIds): Promise => { try { - const tokenContract = new Contract(tokenAddress, ERC20, provider); + const tokenContract = new Contract(tokenAddress, ERC20, provider[chainId]); const decimals = await tokenContract.decimals(); return decimals; } catch (err) { diff --git a/src/scripts/getQuest.ts b/src/scripts/getQuest.ts new file mode 100644 index 0000000..b2020ba --- /dev/null +++ b/src/scripts/getQuest.ts @@ -0,0 +1,68 @@ +import { Contract } from 'ethers'; +import provider from '../config/etherProvider'; +import QuestBoardAbi from '../data/abi/QuestBoardAbi.json'; +import { ChainIds } from '../globals/chainIds'; + +enum VoteType { + NORMAL, + BLACKLIST, + WHITELIST, +} + +enum RewardsType { + FIXED, + RANGE, +} + +enum CloseType { + NORMAL, + ROLLOVER, + DISTRIBUTE, +} + +type QuestTypes = { + voteType: VoteType; + rewardsType: RewardsType; + closeType: CloseType; +}; + +type QuestPeriod = { + // Address of the Quest creator (caller of createQuest() method) + creator: string; + // Address of the ERC20 used for rewards + rewardToken: string; + // Address of the target Gauge + gauge: string; + // Total number of periods for the Quest + duration: bigint; + // Timestamp where the 1st QuestPeriod starts + periodStart: bigint; + // Total amount of rewards paid for this Quest + // If changes were made to the parameters of this Quest, this will account + // any added reward amounts + totalRewardAmount: bigint; + // Total reward amount that can be distributed for each period + rewardAmountPerPeriod: bigint; + // Min Amount of reward for each vote (for 1 veToken) + minRewardPerVote: bigint; + // Max Amount of reward for each vote (for 1 veToken) + maxRewardPerVote: bigint; + // Min Target Bias for the Gauge + minObjectiveVotes: bigint; + // Max Target Bias for the Gauge + maxObjectiveVotes: bigint; + // Quest Types + types: QuestTypes; +}; + +const getQuest = async ( + questBoard: string, + questId: bigint, + chainId: ChainIds, +): Promise => { + const contract = new Contract(questBoard, QuestBoardAbi, provider[chainId]); + const quest = await contract.quests(questId); + return quest; +}; + +export { getQuest, QuestPeriod, QuestTypes, VoteType, RewardsType, CloseType }; diff --git a/src/scripts/getQuestPeriods.ts b/src/scripts/getQuestPeriods.ts index 3206bc5..742a6b2 100644 --- a/src/scripts/getQuestPeriods.ts +++ b/src/scripts/getQuestPeriods.ts @@ -1,6 +1,7 @@ import { Contract } from 'ethers'; import provider from '../config/etherProvider'; import QuestBoardAbi from '../data/abi/QuestBoardAbi.json'; +import { ChainIds } from '../globals/chainIds'; enum PeriodState { ZERO, @@ -28,8 +29,12 @@ type QuestPeriod = { currentState: PeriodState; }; -const getQuestPeriod = async (questBoard: string, questId: bigint): Promise => { - const contract = new Contract(questBoard, QuestBoardAbi, provider); +const getQuestPeriod = async ( + questBoard: string, + questId: bigint, + chainId: ChainIds, +): Promise => { + const contract = new Contract(questBoard, QuestBoardAbi, provider[chainId]); const periods = await contract.getAllQuestPeriodsForQuestId(questId); return periods; }; diff --git a/src/scripts/getSymbolFromGauge.ts b/src/scripts/getSymbolFromGauge.ts index 5d5e97e..6212bf3 100644 --- a/src/scripts/getSymbolFromGauge.ts +++ b/src/scripts/getSymbolFromGauge.ts @@ -1,8 +1,9 @@ import axios from 'axios'; import { ProtocolType } from '../type/protocolType'; -import { Contract, getAddress } from 'ethers'; -import provider from '../config/etherProvider'; +import { Contract, Provider, getAddress } from 'ethers'; +import etherProvider from '../config/etherProvider'; import FxGauge from '../data/abi/FxGauge.json'; +import { ChainIds } from '../globals/chainIds'; const getSymbolFromBalancerGauge = async (gauge: string): Promise => { try { @@ -39,11 +40,23 @@ const getSymbolFromCurveGauge = async (expectedGauge: string): Promise = }; const getBunniChainGauges = async ( - chain: string, + chain: ChainIds, ): Promise<{ address: string; symbol: string }[]> => { + let subgrapghId: string; + switch (chain) { + case ChainIds.MAINNET: + subgrapghId = 'HH4HFj4rFnm5qnkb8MbEdP2V5eD9rZnLJE921YQAs7AV'; + break; + case ChainIds.ARBITRUM: + subgrapghId = 'QmQNz7JfUh4ztY5S8w5dJggyCsGmxYZSgJRd8NRHsJ3KUN'; + break; + default: + return []; + } + try { const res = await axios.post( - `https://api.thegraph.com/subgraphs/name/bunniapp/bunni-${chain}`, + `https://gateway.thegraph.com/api/${process.env.SUBGRAPH_APIKEY}/subgraphs/id/${subgrapghId}`, { query: '{\n bunniTokens(\n where: {gauge_: {address_not: "0x0000000000000000000000000000000000000000"}}\n ) {\n gauge {\n address\n }\n name\n }\n}', @@ -63,15 +76,11 @@ const getBunniChainGauges = async ( } }; -const getSymbolFromBunniGauge = async (expectedGauge: string): Promise => { - const chains = ['mainnet', 'arbitrum']; - - for (const chain of chains) { - const gauges = await getBunniChainGauges(chain); - for (const gauge of gauges) { - if (getAddress(gauge.address) === getAddress(expectedGauge)) { - return gauge.symbol.replace('Bunni ', '').replace(' LP', ''); - } +const getSymbolFromBunniGauge = async (expectedGauge: string, chain: ChainIds): Promise => { + const gauges = await getBunniChainGauges(chain); + for (const gauge of gauges) { + if (getAddress(gauge.address) === getAddress(expectedGauge)) { + return gauge.symbol.replace('Bunni ', '').replace(' LP', ''); } } return ''; @@ -92,7 +101,7 @@ const getSymbolFromCurveLp = async (expectedLp: string): Promise => { return ''; }; -const getSymbolFromFxGauge = async (gauge: string): Promise => { +const getSymbolFromFxGauge = async (gauge: string, provider: Provider): Promise => { try { const gaugeContract = new Contract(gauge, FxGauge, provider); const stakingToken = await gaugeContract.stakingToken(); @@ -110,16 +119,21 @@ const getSymbolFromFxGauge = async (gauge: string): Promise => { } }; -const getSymbolFromGauge = async (gauge: string, protocol: ProtocolType): Promise => { +const getSymbolFromGauge = async ( + gauge: string, + protocol: ProtocolType, + chainId: ChainIds, +): Promise => { + const provider = etherProvider[chainId]; switch (protocol) { case ProtocolType.Balancer: return getSymbolFromBalancerGauge(gauge); case ProtocolType.Curve: return getSymbolFromCurveGauge(gauge); case ProtocolType.Bunni: - return getSymbolFromBunniGauge(gauge); + return getSymbolFromBunniGauge(gauge, chainId); case ProtocolType.Fx: - return getSymbolFromFxGauge(gauge); + return getSymbolFromFxGauge(gauge, provider); default: return ''; } diff --git a/src/scripts/getSymbolFromToken.ts b/src/scripts/getSymbolFromToken.ts index f05a1f4..d5fe612 100644 --- a/src/scripts/getSymbolFromToken.ts +++ b/src/scripts/getSymbolFromToken.ts @@ -1,10 +1,11 @@ import { Contract } from 'ethers'; import provider from '../config/etherProvider'; import ERC20 from '../data/abi/ERC20.json'; +import { ChainIds } from '../globals/chainIds'; -const getSymbolFromToken = async (tokenAddress: string): Promise => { +const getSymbolFromToken = async (tokenAddress: string, chainId: ChainIds): Promise => { try { - const tokenContract = new Contract(tokenAddress, ERC20, provider); + const tokenContract = new Contract(tokenAddress, ERC20, provider[chainId]); const symbol = await tokenContract.symbol(); return symbol; } catch (err) {