Skip to content

add Merkl rewards to existing pools #1827

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/adaptors/gamma/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const { request, gql } = require('graphql-request');
const sdk = require('@defillama/sdk');
const utils = require('../utils');
const { print } = require('graphql');
const { addMerklRewardApy } = require('../merkl/merkl-additional-reward');

const EXCHANGES_API = {
uniswapv3: '',
Expand Down Expand Up @@ -388,11 +389,13 @@ const getApy = async () => {
'0x431f6e577a431d9ee87a535fde2db830e352e33c',
'0xed17209ab7f9224e29cc9894fa14a011f37b6115',
];
return pools.flat().map((i) => ({
const data = pools.flat().map((i) => ({
...i,
apyReward: x.includes(i.pool) || i.chain === 'Manta' ? null : i.apyReward,
rewardTokens: x.includes(i.pool) || i.chain === 'Manta' ? null : i.rewardTokens,
})).filter(p => p.chain != 'Binance');

return addMerklRewardApy(data, 'gamma', (p) => p.pool.split('-')[0]);
};

module.exports = {
Expand Down
23 changes: 23 additions & 0 deletions src/adaptors/merkl/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
exports.networks = {
1: 'ethereum',
137: 'polygon',
10: 'optimism',
42161: 'arbitrum',
1101: 'polygon_zkevm',
8453: 'base',
60808: 'bob',
146: 'sonic',
43114: 'avax',
80094: 'berachain',
56: 'bsc',
};

// Protocols that should not be listed under Merkl
// as they already have their own adapters.
exports.protocolsBlacklist = [
'euler',
'crosscurve',
'aerodrome',
'gamma',
'uniswap',
];
11 changes: 2 additions & 9 deletions src/adaptors/merkl/index.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
const sdk = require('@defillama/sdk');
const utils = require('../utils');

const networks = {
1: 'ethereum',
137: 'polygon',
10: 'optimism',
42161: 'arbitrum',
1101: 'polygon_zkevm',
8453: 'base',
60808: 'bob',
};
const { networks } = require('./config');

// Protocols that should not be listed under Merkl
// as they already have their own adapters.
Expand Down Expand Up @@ -47,6 +39,7 @@ const main = async () => {
);
} catch (err) {
console.log('failed to fetch Merkl data on chain ' + chain);
break;
}

if (data.length === 0) {
Expand Down
68 changes: 68 additions & 0 deletions src/adaptors/merkl/merkl-additional-reward.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
const { networks } = require('./config');
const { getData } = require('../utils');

exports.addMerklRewardApy = async (
pools,
protocolId,
poolAddressGetter,
) => {
try {
let merklPools = [];
let pageI = 0;

while(true) {
let data;
try {
data = await getData(`https://api.merkl.xyz/v4/opportunities?mainProtocolId=${protocolId}&status=LIVE&items=100&page=${pageI}`);
} catch (err) {
console.log(`failed to fetch Merkl data for ${protocolId}: ${err}`);
break;
}

if (data.length === 0) {
break;
}

merklPools.push(...data);
pageI++;
}


const merklPoolsMap = Object.fromEntries(Object.keys(networks).map(id => [networks[id], {}]));
merklPools.forEach(pool => {
if (!networks[pool.chainId]) {
return;
}

merklPoolsMap[networks[pool.chainId]][pool.identifier.toLowerCase()] = {
apyReward: pool.apr,
rewardTokens: [...new Set(pool.rewardsRecord?.breakdowns.map(x => x.token.address) || [])]
}
});

return pools.map(pool => {
const poolAddress = poolAddressGetter ? poolAddressGetter(pool) : pool.pool;
const merklRewards = merklPoolsMap[pool.chain.toLowerCase()][poolAddress.toLowerCase()];

if (!merklRewards) {
return pool;
}

// if the data is already present, don't overwrite it
if (pool.apyReward || (pool.rewardTokens && pool.rewardTokens.length !== 0)) {
console.log('pool already has apyReward or rewardTokens', pool.pool);
return pool;
}

return {
...pool,
...merklRewards,
}
});
} catch (err) {
console.log(`Failed to add Merkl reward apy to ${protocolId}: ${err}`);

// If we fail to fetch Merkl data, just return the original pools
return pools;
}
};
6 changes: 5 additions & 1 deletion src/adaptors/uniswap-v2/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const sdk = require('@defillama/sdk');
const { request, gql } = require('graphql-request');

const utils = require('../utils');
const { addMerklRewardApy } = require('../merkl/merkl-additional-reward');

const chains = {
ethereum: sdk.graph.modifyEndpoint(
Expand Down Expand Up @@ -126,7 +127,10 @@ const main = async (timestamp = null) => {
}
}

return data.filter((p) => utils.keepFinite(p));
return addMerklRewardApy(
data.filter((p) => utils.keepFinite(p)),
'uniswap'
);
};

module.exports = {
Expand Down
8 changes: 6 additions & 2 deletions src/adaptors/uniswap-v3/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const { EstimatedFees } = require('./estimateFee.ts');
const { checkStablecoin } = require('../../handlers/triggerEnrichment');
const { boundaries } = require('../../utils/exclude');
const getOnchainPools = require('./onchain');
const { addMerklRewardApy } = require('../merkl/merkl-additional-reward');

const chains = {
ethereum: sdk.graph.modifyEndpoint(
Expand Down Expand Up @@ -352,7 +353,8 @@ const main = async (timestamp = null) => {
);
}
data.push(...(await getOnchainPools()))
return data
return addMerklRewardApy(
data
.flat()
.filter(
(p) =>
Expand All @@ -361,7 +363,9 @@ const main = async (timestamp = null) => {
'0x0c6d9d0f82ed2e0b86c4d3e9a9febf95415d1b76',
'0xc809d13e9ea08f296d3b32d4c69d46ff90f73fd8',
].includes(p.pool)
);
),
'uniswap'
);
};

module.exports = {
Expand Down
Loading