|
| 1 | +const { request, gql } = require('graphql-request'); |
| 2 | +const utils = require('../utils'); |
| 3 | +const axios = require('axios'); |
| 4 | + |
| 5 | +const START_TIME = 1732071601; // First silo yield distribution at Season 4. |
| 6 | +const API = "https://api.pinto.money/silo/yield" |
| 7 | +const SUBGRAPH = "https://graph.pinto.money/pinto/" |
| 8 | + |
| 9 | +async function getPools(timestamp = null) { |
| 10 | + const pools = await getPoolsForChain("base", timestamp); |
| 11 | + return pools.flat(); |
| 12 | +} |
| 13 | + |
| 14 | +async function getPoolsForChain(chain, timestamp) { |
| 15 | + |
| 16 | + if (timestamp && timestamp < START_TIME) { |
| 17 | + return []; |
| 18 | + } |
| 19 | + |
| 20 | + const resultPools = []; |
| 21 | + |
| 22 | + // When a timestamp is specified, determine which block to use |
| 23 | + let block; |
| 24 | + if (timestamp) { |
| 25 | + [block] = await utils.getBlocksByTime([timestamp], chain); |
| 26 | + } |
| 27 | + |
| 28 | + // Query subgraph to identify each yield-bearing pool and its info |
| 29 | + const poolData = await request(SUBGRAPH, gql` |
| 30 | + { |
| 31 | + beans${block ? `(block: {number: ${block}})` : ''} { |
| 32 | + id |
| 33 | + currentSeason { |
| 34 | + season |
| 35 | + } |
| 36 | + pools { |
| 37 | + id |
| 38 | + liquidityUSD |
| 39 | + tokens { |
| 40 | + id |
| 41 | + name |
| 42 | + } |
| 43 | + } |
| 44 | + } |
| 45 | + }` |
| 46 | + ); |
| 47 | + |
| 48 | + for (const bean of poolData.beans) { |
| 49 | + |
| 50 | + // Get apy info |
| 51 | + const apy = await axios.post(API, { |
| 52 | + season: bean.currentSeason.season, |
| 53 | + emaWindows: [720], |
| 54 | + tokens: bean.pools.map(p => p.id), |
| 55 | + options: { |
| 56 | + initType: 'NEW' |
| 57 | + } |
| 58 | + }); |
| 59 | + // Uses the available window if fewer datapoints were available |
| 60 | + const yields = apy.data.yields[Object.keys(apy.data.yields)[0]]; |
| 61 | + const pools = bean.pools.filter(p => yields[p.id]); |
| 62 | + |
| 63 | + // Add results for each pool |
| 64 | + for (const pool of pools) { |
| 65 | + // Sort PINTO to be first in the token list |
| 66 | + const tokens = pool.tokens[0].name === 'PINTO' ? pool.tokens : [pool.tokens[1], pool.tokens[0]]; |
| 67 | + resultPools.push({ |
| 68 | + pool: (`${pool.id}-${chain}`).toLowerCase(), |
| 69 | + chain: utils.formatChain(chain), |
| 70 | + project: 'pinto', |
| 71 | + symbol: `${tokens[0].name}-${tokens[1].name}`, |
| 72 | + tvlUsd: parseInt(pool.liquidityUSD), |
| 73 | + apyReward: Math.round(yields[pool.id].bean * 10000) / 100, |
| 74 | + rewardTokens: [bean.id], |
| 75 | + underlyingTokens: tokens.map(p => p.id.toLowerCase()), |
| 76 | + poolMeta: 'Pinto Silo' |
| 77 | + }); |
| 78 | + } |
| 79 | + } |
| 80 | + return resultPools; |
| 81 | +} |
| 82 | + |
| 83 | +module.exports = { |
| 84 | + timetravel: true, |
| 85 | + apy: getPools, |
| 86 | + url: 'https://pinto.money/' |
| 87 | +}; |
0 commit comments