Skip to content

Commit

Permalink
add webhook for tvl spikes (DefiLlama#239)
Browse files Browse the repository at this point in the history
  • Loading branch information
slasher125 authored Aug 20, 2022
1 parent 38b041c commit 3e1e2d3
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 9 deletions.
1 change: 1 addition & 0 deletions .github/workflows/master.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ jobs:
ALCHEMY_CONNECTION_ARBITRUM: ${{ secrets.ALCHEMY_CONNECTION_ARBITRUM }}
XDAI_RPC: ${{ secrets.XDAI_RPC }}
CRONOS_RPC: ${{ secrets.CRONOS_RPC }}
TVL_SPIKE_WEBHOOK: ${{ secrets.TVL_SPIKE_WEBHOOK }}
1 change: 1 addition & 0 deletions env.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ module.exports = {
ALCHEMY_CONNECTION_ARBITRUM: process.env.ALCHEMY_CONNECTION_ARBITRUM,
XDAI_RPC: process.env.XDAI_RPC,
CRONOS_RPC: process.env.CRONOS_RPC,
TVL_SPIKE_WEBHOOK: process.env.TVL_SPIKE_WEBHOOK,
// ADAPTOR LIST
ADAPTORS: JSON.stringify(
fs
Expand Down
1 change: 1 addition & 0 deletions serverless.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ functions:
ALCHEMY_CONNECTION_ARBITRUM: ${file(./env.js):ALCHEMY_CONNECTION_ARBITRUM}
XDAI_RPC: ${file(./env.js):XDAI_RPC}
CRONOS_RPC: ${file(./env.js):CRONOS_RPC}
TVL_SPIKE_WEBHOOK: ${file(./env.js):TVL_SPIKE_WEBHOOK}

# --- data enrichment
triggerEnrichment:
Expand Down
37 changes: 28 additions & 9 deletions src/handlers/triggerAdaptor.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const { aggQuery } = require('./getPools');
const AppError = require('../utils/appError');
const exclude = require('../utils/exclude');
const dbConnection = require('../utils/dbConnection.js');
const { sendMessage } = require('../utils/discordWebhook');

module.exports.handler = async (event, context) => {
context.callbackWaitsForEmptyEventLoop = false;
Expand Down Expand Up @@ -120,31 +121,49 @@ const main = async (body) => {
const dataInitial = await getProject(body.adaptor);

const dataDB = [];
const nHours = 5;
const tvlDeltaMultiplier = 5;
const timedeltaLimit = 60 * 60 * nHours * 1000;
const droppedPools = [];
for (const p of data) {
const x = dataInitial.find((e) => e.pool === p.pool);
if (x === undefined) {
dataDB.push(p);
continue;
}
// if existing pool, check conditions
timedelta = timestamp - x.timestamp;
const nHours = 5;
const tvlDeltaMultiplier = 5;
timedeltaLimit = 60 * 60 * nHours * 1000;
// skip the update if tvl at t is ntimes larger than tvl at t-1 && timedelta conditions is met
const timedelta = timestamp - x.timestamp;
// skip the update if tvl at t is ntimes larger than tvl at t-1 && timedelta condition is met
if (
p.tvlUsd > x.tvlUsd * tvlDeltaMultiplier &&
timedelta < timedeltaLimit
) {
console.log(`removing pool ${p.pool}`);
droppedPools.push({
pool: p.pool,
symbol: p.symbol,
tvlUsd: p.tvlUsd,
tvlUsdDB: x.tvlUsd,
tvlMultiplier: p.tvlUsd / x.tvlUsd,
lastUpdate: x.timestamp,
hoursUntilNextUpdate: 6 - timedelta / 1000 / 60 / 60,
});
continue;
}
dataDB.push(p);
}
if (dataDB.length < data.length)
console.log(
`removed ${data.length - dataDB.length} sample(s) prior to insert`
);
const delta = data.length - dataDB.length;
if (delta > 0) {
console.log(`removed ${delta} sample(s) prior to insert`);
// send discord message
const message = droppedPools
.map(
(p) =>
`${p.pool} (${p.symbol}): TVL ${p.tvlMultiplier}x -> disabling it`
)
.join('\n');
await sendMessage(message, process.env.TVL_SPIKE_WEBHOOK);
}

const response = await insertPools(dataDB);
console.log(response);
Expand Down
28 changes: 28 additions & 0 deletions src/utils/discordWebhook.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const fetch = require('node-fetch');

// copy pasta from defillama-server
module.exports.sendMessage = async (message, webhookUrl, formatted = true) => {
const formattedMessage = formatted ? '```\n' + message + '\n```' : message; // Put it into a code block to prevent the format from getting messed up
if (formattedMessage.length >= 2000) {
const lines = message.split('\n');
if (lines.length <= 2) {
throw new Error('Lines are too long, reaching infinite recursivity');
}
const mid = Math.round(lines.length / 2);
await sendMessage(lines.slice(0, mid).join('\n'), webhookUrl);
await sendMessage(lines.slice(mid).join('\n'), webhookUrl);
return;
}
// Example: https://gist.github.com/dragonwocky/ea61c8d21db17913a43da92efe0de634
// Docs: https://gist.github.com/dragonwocky/ea61c8d21db17913a43da92efe0de634
const response = await fetch(`${webhookUrl}?wait=true`, {
method: 'post',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
content: formattedMessage,
}),
}).then((body) => body.json());
console.log('discord', response);
};

0 comments on commit 3e1e2d3

Please sign in to comment.