diff --git a/packages/address-book/scripts/checkOracles.ts b/packages/address-book/scripts/checkOracles.ts index 81b3a572f..99967c9bb 100644 --- a/packages/address-book/scripts/checkOracles.ts +++ b/packages/address-book/scripts/checkOracles.ts @@ -3,7 +3,7 @@ import { addressBook } from '../address-book'; type ChainId = keyof typeof addressBook; const allChains = Object.keys(addressBook) as ChainId[]; -const skipPrices: boolean = true; +const skipPrices = true; type Vault = { id: string; @@ -16,16 +16,13 @@ async function fetchVaults(): Promise> { const response = await fetch('https://api.beefy.finance/vaults'); const vaults = (await response.json()) as Vault[]; - return vaults.reduce( - (acc, vault) => { - if (!acc[vault.chain]) { - acc[vault.chain] = []; - } - acc[vault.chain].push(vault); - return acc; - }, - {} as Record - ); + return vaults.reduce((acc, vault) => { + if (!acc[vault.chain]) { + acc[vault.chain] = []; + } + acc[vault.chain].push(vault); + return acc; + }, {} as Record); } async function fetchPrices(): Promise> { @@ -38,15 +35,12 @@ async function fetchPrices(): Promise> { responses.map(async r => (await r.json()) as Record) ); const joined = Object.assign({}, ...data); - return Object.entries(joined).reduce( - (acc, [key, value]) => { - if (typeof value === 'number' && isFinite(value) && !isNaN(value)) { - acc[key] = value; - } - return acc; - }, - {} as Record - ); + return Object.entries(joined).reduce((acc, [key, value]) => { + if (typeof value === 'number' && isFinite(value) && !isNaN(value)) { + acc[key] = value; + } + return acc; + }, {} as Record); } async function checkChain(chainId: ChainId, vaults: Vault[], prices: Record) { diff --git a/src/abis/ethereum/AcceleratingDistributor.ts b/src/abis/ethereum/AcceleratingDistributor.ts index eba998e42..c21e4c3a3 100644 --- a/src/abis/ethereum/AcceleratingDistributor.ts +++ b/src/abis/ethereum/AcceleratingDistributor.ts @@ -1,693 +1,693 @@ const AcceleratingDistributor = [ { - "inputs": [ + inputs: [ { - "internalType": "address", - "name": "_rewardToken", - "type": "address" - } + internalType: 'address', + name: '_rewardToken', + type: 'address', + }, ], - "stateMutability": "nonpayable", - "type": "constructor" + stateMutability: 'nonpayable', + type: 'constructor', }, { - "anonymous": false, - "inputs": [ + anonymous: false, + inputs: [ { - "indexed": true, - "internalType": "address", - "name": "token", - "type": "address" + indexed: true, + internalType: 'address', + name: 'token', + type: 'address', }, { - "indexed": true, - "internalType": "address", - "name": "user", - "type": "address" + indexed: true, + internalType: 'address', + name: 'user', + type: 'address', }, { - "indexed": false, - "internalType": "uint256", - "name": "tokenCumulativeStaked", - "type": "uint256" - } + indexed: false, + internalType: 'uint256', + name: 'tokenCumulativeStaked', + type: 'uint256', + }, ], - "name": "Exit", - "type": "event" + name: 'Exit', + type: 'event', }, { - "anonymous": false, - "inputs": [ + anonymous: false, + inputs: [ { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" + indexed: true, + internalType: 'address', + name: 'previousOwner', + type: 'address', }, { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } + indexed: true, + internalType: 'address', + name: 'newOwner', + type: 'address', + }, ], - "name": "OwnershipTransferred", - "type": "event" + name: 'OwnershipTransferred', + type: 'event', }, { - "anonymous": false, - "inputs": [ + anonymous: false, + inputs: [ { - "indexed": true, - "internalType": "address", - "name": "token", - "type": "address" + indexed: true, + internalType: 'address', + name: 'token', + type: 'address', }, { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, ], - "name": "RecoverToken", - "type": "event" + name: 'RecoverToken', + type: 'event', }, { - "anonymous": false, - "inputs": [ + anonymous: false, + inputs: [ { - "indexed": true, - "internalType": "address", - "name": "token", - "type": "address" + indexed: true, + internalType: 'address', + name: 'token', + type: 'address', }, { - "indexed": true, - "internalType": "address", - "name": "user", - "type": "address" + indexed: true, + internalType: 'address', + name: 'user', + type: 'address', }, { - "indexed": false, - "internalType": "uint256", - "name": "rewardsToSend", - "type": "uint256" + indexed: false, + internalType: 'uint256', + name: 'rewardsToSend', + type: 'uint256', }, { - "indexed": false, - "internalType": "uint256", - "name": "tokenLastUpdateTime", - "type": "uint256" + indexed: false, + internalType: 'uint256', + name: 'tokenLastUpdateTime', + type: 'uint256', }, { - "indexed": false, - "internalType": "uint256", - "name": "tokenRewardPerTokenStored", - "type": "uint256" + indexed: false, + internalType: 'uint256', + name: 'tokenRewardPerTokenStored', + type: 'uint256', }, { - "indexed": false, - "internalType": "uint256", - "name": "userRewardsOutstanding", - "type": "uint256" + indexed: false, + internalType: 'uint256', + name: 'userRewardsOutstanding', + type: 'uint256', }, { - "indexed": false, - "internalType": "uint256", - "name": "userRewardsPaidPerToken", - "type": "uint256" - } + indexed: false, + internalType: 'uint256', + name: 'userRewardsPaidPerToken', + type: 'uint256', + }, ], - "name": "RewardsWithdrawn", - "type": "event" + name: 'RewardsWithdrawn', + type: 'event', }, { - "anonymous": false, - "inputs": [ + anonymous: false, + inputs: [ { - "indexed": true, - "internalType": "address", - "name": "token", - "type": "address" + indexed: true, + internalType: 'address', + name: 'token', + type: 'address', }, { - "indexed": true, - "internalType": "address", - "name": "user", - "type": "address" + indexed: true, + internalType: 'address', + name: 'user', + type: 'address', }, { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', }, { - "indexed": false, - "internalType": "uint256", - "name": "averageDepositTime", - "type": "uint256" + indexed: false, + internalType: 'uint256', + name: 'averageDepositTime', + type: 'uint256', }, { - "indexed": false, - "internalType": "uint256", - "name": "cumulativeBalance", - "type": "uint256" + indexed: false, + internalType: 'uint256', + name: 'cumulativeBalance', + type: 'uint256', }, { - "indexed": false, - "internalType": "uint256", - "name": "tokenCumulativeStaked", - "type": "uint256" - } + indexed: false, + internalType: 'uint256', + name: 'tokenCumulativeStaked', + type: 'uint256', + }, ], - "name": "Stake", - "type": "event" + name: 'Stake', + type: 'event', }, { - "anonymous": false, - "inputs": [ + anonymous: false, + inputs: [ { - "indexed": true, - "internalType": "address", - "name": "token", - "type": "address" + indexed: true, + internalType: 'address', + name: 'token', + type: 'address', }, { - "indexed": false, - "internalType": "bool", - "name": "enabled", - "type": "bool" + indexed: false, + internalType: 'bool', + name: 'enabled', + type: 'bool', }, { - "indexed": false, - "internalType": "uint256", - "name": "baseEmissionRate", - "type": "uint256" + indexed: false, + internalType: 'uint256', + name: 'baseEmissionRate', + type: 'uint256', }, { - "indexed": false, - "internalType": "uint256", - "name": "maxMultiplier", - "type": "uint256" + indexed: false, + internalType: 'uint256', + name: 'maxMultiplier', + type: 'uint256', }, { - "indexed": false, - "internalType": "uint256", - "name": "secondsToMaxMultiplier", - "type": "uint256" + indexed: false, + internalType: 'uint256', + name: 'secondsToMaxMultiplier', + type: 'uint256', }, { - "indexed": false, - "internalType": "uint256", - "name": "lastUpdateTime", - "type": "uint256" - } + indexed: false, + internalType: 'uint256', + name: 'lastUpdateTime', + type: 'uint256', + }, ], - "name": "TokenConfiguredForStaking", - "type": "event" + name: 'TokenConfiguredForStaking', + type: 'event', }, { - "anonymous": false, - "inputs": [ + anonymous: false, + inputs: [ { - "indexed": true, - "internalType": "address", - "name": "token", - "type": "address" + indexed: true, + internalType: 'address', + name: 'token', + type: 'address', }, { - "indexed": true, - "internalType": "address", - "name": "user", - "type": "address" + indexed: true, + internalType: 'address', + name: 'user', + type: 'address', }, { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', }, { - "indexed": false, - "internalType": "uint256", - "name": "remainingCumulativeBalance", - "type": "uint256" + indexed: false, + internalType: 'uint256', + name: 'remainingCumulativeBalance', + type: 'uint256', }, { - "indexed": false, - "internalType": "uint256", - "name": "tokenCumulativeStaked", - "type": "uint256" - } + indexed: false, + internalType: 'uint256', + name: 'tokenCumulativeStaked', + type: 'uint256', + }, ], - "name": "Unstake", - "type": "event" + name: 'Unstake', + type: 'event', }, { - "inputs": [ + inputs: [ { - "internalType": "address", - "name": "stakedToken", - "type": "address" - } + internalType: 'address', + name: 'stakedToken', + type: 'address', + }, ], - "name": "baseRewardPerToken", - "outputs": [ + name: 'baseRewardPerToken', + outputs: [ { - "internalType": "uint256", - "name": "", - "type": "uint256" - } + internalType: 'uint256', + name: '', + type: 'uint256', + }, ], - "stateMutability": "view", - "type": "function" + stateMutability: 'view', + type: 'function', }, { - "inputs": [ + inputs: [ { - "internalType": "address", - "name": "stakedToken", - "type": "address" + internalType: 'address', + name: 'stakedToken', + type: 'address', }, { - "internalType": "bool", - "name": "enabled", - "type": "bool" + internalType: 'bool', + name: 'enabled', + type: 'bool', }, { - "internalType": "uint256", - "name": "baseEmissionRate", - "type": "uint256" + internalType: 'uint256', + name: 'baseEmissionRate', + type: 'uint256', }, { - "internalType": "uint256", - "name": "maxMultiplier", - "type": "uint256" + internalType: 'uint256', + name: 'maxMultiplier', + type: 'uint256', }, { - "internalType": "uint256", - "name": "secondsToMaxMultiplier", - "type": "uint256" - } + internalType: 'uint256', + name: 'secondsToMaxMultiplier', + type: 'uint256', + }, ], - "name": "configureStakingToken", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + name: 'configureStakingToken', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', }, { - "inputs": [ + inputs: [ { - "internalType": "address", - "name": "stakedToken", - "type": "address" - } + internalType: 'address', + name: 'stakedToken', + type: 'address', + }, ], - "name": "exit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + name: 'exit', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', }, { - "inputs": [ + inputs: [ { - "internalType": "address", - "name": "stakedToken", - "type": "address" + internalType: 'address', + name: 'stakedToken', + type: 'address', }, { - "internalType": "address", - "name": "account", - "type": "address" + internalType: 'address', + name: 'account', + type: 'address', }, { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, ], - "name": "getAverageDepositTimePostDeposit", - "outputs": [ + name: 'getAverageDepositTimePostDeposit', + outputs: [ { - "internalType": "uint256", - "name": "", - "type": "uint256" - } + internalType: 'uint256', + name: '', + type: 'uint256', + }, ], - "stateMutability": "view", - "type": "function" + stateMutability: 'view', + type: 'function', }, { - "inputs": [ + inputs: [ { - "internalType": "address", - "name": "stakedToken", - "type": "address" - } + internalType: 'address', + name: 'stakedToken', + type: 'address', + }, ], - "name": "getCumulativeStaked", - "outputs": [ + name: 'getCumulativeStaked', + outputs: [ { - "internalType": "uint256", - "name": "", - "type": "uint256" - } + internalType: 'uint256', + name: '', + type: 'uint256', + }, ], - "stateMutability": "view", - "type": "function" + stateMutability: 'view', + type: 'function', }, { - "inputs": [], - "name": "getCurrentTime", - "outputs": [ + inputs: [], + name: 'getCurrentTime', + outputs: [ { - "internalType": "uint256", - "name": "", - "type": "uint256" - } + internalType: 'uint256', + name: '', + type: 'uint256', + }, ], - "stateMutability": "view", - "type": "function" + stateMutability: 'view', + type: 'function', }, { - "inputs": [ + inputs: [ { - "internalType": "address", - "name": "stakedToken", - "type": "address" + internalType: 'address', + name: 'stakedToken', + type: 'address', }, { - "internalType": "address", - "name": "account", - "type": "address" - } + internalType: 'address', + name: 'account', + type: 'address', + }, ], - "name": "getOutstandingRewards", - "outputs": [ + name: 'getOutstandingRewards', + outputs: [ { - "internalType": "uint256", - "name": "", - "type": "uint256" - } + internalType: 'uint256', + name: '', + type: 'uint256', + }, ], - "stateMutability": "view", - "type": "function" + stateMutability: 'view', + type: 'function', }, { - "inputs": [ + inputs: [ { - "internalType": "address", - "name": "stakedToken", - "type": "address" + internalType: 'address', + name: 'stakedToken', + type: 'address', }, { - "internalType": "address", - "name": "account", - "type": "address" - } + internalType: 'address', + name: 'account', + type: 'address', + }, ], - "name": "getTimeSinceAverageDeposit", - "outputs": [ + name: 'getTimeSinceAverageDeposit', + outputs: [ { - "internalType": "uint256", - "name": "", - "type": "uint256" - } + internalType: 'uint256', + name: '', + type: 'uint256', + }, ], - "stateMutability": "view", - "type": "function" + stateMutability: 'view', + type: 'function', }, { - "inputs": [ + inputs: [ { - "internalType": "address", - "name": "stakedToken", - "type": "address" + internalType: 'address', + name: 'stakedToken', + type: 'address', }, { - "internalType": "address", - "name": "account", - "type": "address" - } + internalType: 'address', + name: 'account', + type: 'address', + }, ], - "name": "getUserRewardMultiplier", - "outputs": [ + name: 'getUserRewardMultiplier', + outputs: [ { - "internalType": "uint256", - "name": "", - "type": "uint256" - } + internalType: 'uint256', + name: '', + type: 'uint256', + }, ], - "stateMutability": "view", - "type": "function" + stateMutability: 'view', + type: 'function', }, { - "inputs": [ + inputs: [ { - "internalType": "address", - "name": "stakedToken", - "type": "address" + internalType: 'address', + name: 'stakedToken', + type: 'address', }, { - "internalType": "address", - "name": "account", - "type": "address" - } + internalType: 'address', + name: 'account', + type: 'address', + }, ], - "name": "getUserStake", - "outputs": [ + name: 'getUserStake', + outputs: [ { - "components": [ + components: [ { - "internalType": "uint256", - "name": "cumulativeBalance", - "type": "uint256" + internalType: 'uint256', + name: 'cumulativeBalance', + type: 'uint256', }, { - "internalType": "uint256", - "name": "averageDepositTime", - "type": "uint256" + internalType: 'uint256', + name: 'averageDepositTime', + type: 'uint256', }, { - "internalType": "uint256", - "name": "rewardsAccumulatedPerToken", - "type": "uint256" + internalType: 'uint256', + name: 'rewardsAccumulatedPerToken', + type: 'uint256', }, { - "internalType": "uint256", - "name": "rewardsOutstanding", - "type": "uint256" - } + internalType: 'uint256', + name: 'rewardsOutstanding', + type: 'uint256', + }, ], - "internalType": "struct AcceleratingDistributor.UserDeposit", - "name": "", - "type": "tuple" - } + internalType: 'struct AcceleratingDistributor.UserDeposit', + name: '', + type: 'tuple', + }, ], - "stateMutability": "view", - "type": "function" + stateMutability: 'view', + type: 'function', }, { - "inputs": [ + inputs: [ { - "internalType": "bytes[]", - "name": "data", - "type": "bytes[]" - } + internalType: 'bytes[]', + name: 'data', + type: 'bytes[]', + }, ], - "name": "multicall", - "outputs": [ + name: 'multicall', + outputs: [ { - "internalType": "bytes[]", - "name": "results", - "type": "bytes[]" - } + internalType: 'bytes[]', + name: 'results', + type: 'bytes[]', + }, ], - "stateMutability": "nonpayable", - "type": "function" + stateMutability: 'nonpayable', + type: 'function', }, { - "inputs": [], - "name": "owner", - "outputs": [ + inputs: [], + name: 'owner', + outputs: [ { - "internalType": "address", - "name": "", - "type": "address" - } + internalType: 'address', + name: '', + type: 'address', + }, ], - "stateMutability": "view", - "type": "function" + stateMutability: 'view', + type: 'function', }, { - "inputs": [ + inputs: [ { - "internalType": "address", - "name": "token", - "type": "address" - } + internalType: 'address', + name: 'token', + type: 'address', + }, ], - "name": "recoverToken", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + name: 'recoverToken', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', }, { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + inputs: [], + name: 'renounceOwnership', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', }, { - "inputs": [], - "name": "rewardToken", - "outputs": [ + inputs: [], + name: 'rewardToken', + outputs: [ { - "internalType": "contract IERC20", - "name": "", - "type": "address" - } + internalType: 'contract IERC20', + name: '', + type: 'address', + }, ], - "stateMutability": "view", - "type": "function" + stateMutability: 'view', + type: 'function', }, { - "inputs": [ + inputs: [ { - "internalType": "address", - "name": "stakedToken", - "type": "address" + internalType: 'address', + name: 'stakedToken', + type: 'address', }, { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, ], - "name": "stake", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + name: 'stake', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', }, { - "inputs": [ + inputs: [ { - "internalType": "address", - "name": "stakedToken", - "type": "address" + internalType: 'address', + name: 'stakedToken', + type: 'address', }, { - "internalType": "uint256", - "name": "amount", - "type": "uint256" + internalType: 'uint256', + name: 'amount', + type: 'uint256', }, { - "internalType": "address", - "name": "beneficiary", - "type": "address" - } + internalType: 'address', + name: 'beneficiary', + type: 'address', + }, ], - "name": "stakeFor", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + name: 'stakeFor', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', }, { - "inputs": [ + inputs: [ { - "internalType": "address", - "name": "", - "type": "address" - } + internalType: 'address', + name: '', + type: 'address', + }, ], - "name": "stakingTokens", - "outputs": [ + name: 'stakingTokens', + outputs: [ { - "internalType": "bool", - "name": "enabled", - "type": "bool" + internalType: 'bool', + name: 'enabled', + type: 'bool', }, { - "internalType": "uint256", - "name": "baseEmissionRate", - "type": "uint256" + internalType: 'uint256', + name: 'baseEmissionRate', + type: 'uint256', }, { - "internalType": "uint256", - "name": "maxMultiplier", - "type": "uint256" + internalType: 'uint256', + name: 'maxMultiplier', + type: 'uint256', }, { - "internalType": "uint256", - "name": "secondsToMaxMultiplier", - "type": "uint256" + internalType: 'uint256', + name: 'secondsToMaxMultiplier', + type: 'uint256', }, { - "internalType": "uint256", - "name": "cumulativeStaked", - "type": "uint256" + internalType: 'uint256', + name: 'cumulativeStaked', + type: 'uint256', }, { - "internalType": "uint256", - "name": "rewardPerTokenStored", - "type": "uint256" + internalType: 'uint256', + name: 'rewardPerTokenStored', + type: 'uint256', }, { - "internalType": "uint256", - "name": "lastUpdateTime", - "type": "uint256" - } + internalType: 'uint256', + name: 'lastUpdateTime', + type: 'uint256', + }, ], - "stateMutability": "view", - "type": "function" + stateMutability: 'view', + type: 'function', }, { - "inputs": [ + inputs: [ { - "internalType": "address", - "name": "newOwner", - "type": "address" - } + internalType: 'address', + name: 'newOwner', + type: 'address', + }, ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + name: 'transferOwnership', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', }, { - "inputs": [ + inputs: [ { - "internalType": "address", - "name": "stakedToken", - "type": "address" + internalType: 'address', + name: 'stakedToken', + type: 'address', }, { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, ], - "name": "unstake", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + name: 'unstake', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', }, { - "inputs": [ - { - "internalType": "address", - "name": "stakedToken", - "type": "address" - } - ], - "name": "withdrawReward", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } + inputs: [ + { + internalType: 'address', + name: 'stakedToken', + type: 'address', + }, + ], + name: 'withdrawReward', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, ] as const; export default AcceleratingDistributor; diff --git a/src/api/articles/fetchArticlesData.ts b/src/api/articles/fetchArticlesData.ts new file mode 100644 index 000000000..b90db5434 --- /dev/null +++ b/src/api/articles/fetchArticlesData.ts @@ -0,0 +1,46 @@ +import { getKey, setKey } from '../../utils/cache'; +import { ArticleInterface, ArticlesResponse } from './types'; + +const REDIS_KEY = 'ARTICLES'; + +let articles: ArticleInterface[] = []; + +const INIT_DELAY = Number(process.env.BLOG_INIT_DELAY || 4 * 1000); +const REFRESH_INTERVAL = 12 * 60 * 1000; + +export const getAllArticles = () => articles; + +export const getLastArticle = () => articles[0]; + +export const updateArticles = async () => { + console.log('> updating articles'); + const start = Date.now(); + try { + articles = await fetch('https://beefy.com/api/articles.json') + .then(res => res.json()) + .then((res: ArticleInterface[]) => Object.values(res)); + + saveToRedis(); + console.log(`> updated articles (${(Date.now() - start) / 1000}s)`); + } catch (err) { + console.error(err); + } + setTimeout(updateArticles, REFRESH_INTERVAL); +}; + +async function loadFromRedis() { + const cachedArticles = await getKey(REDIS_KEY); + + if (cachedArticles && typeof cachedArticles === 'object') { + articles = cachedArticles; + } +} + +async function saveToRedis() { + await setKey(REDIS_KEY, articles); +} + +export async function initArticlesService() { + await loadFromRedis(); + setTimeout(updateArticles, INIT_DELAY); +} diff --git a/src/api/articles/index.ts b/src/api/articles/index.ts new file mode 100644 index 000000000..ddbd8ae89 --- /dev/null +++ b/src/api/articles/index.ts @@ -0,0 +1,23 @@ +import { getAllArticles, getLastArticle } from './fetchArticlesData'; + +export const getArticles = async (ctx: any) => { + try { + const allArticles = getAllArticles(); + ctx.status = 200; + ctx.body = [...allArticles]; + } catch (err) { + console.error(err); + ctx.status = 500; + } +}; + +export const getLatestArticle = async (ctx: any) => { + try { + const lastArticle = getLastArticle(); + ctx.status = 200; + ctx.body = lastArticle; + } catch (err) { + console.error(err); + ctx.status = 500; + } +}; diff --git a/src/api/articles/types.ts b/src/api/articles/types.ts new file mode 100644 index 000000000..a882e4fef --- /dev/null +++ b/src/api/articles/types.ts @@ -0,0 +1,9 @@ +export type ArticlesResponse = ArticleInterface[]; + +export interface ArticleInterface { + id: string; + title: string; + description: string; + date: number; + url: string; +} diff --git a/src/api/stats/ethereum/getAcrossApys.js b/src/api/stats/ethereum/getAcrossApys.js index 8928a8ccb..950448595 100644 --- a/src/api/stats/ethereum/getAcrossApys.js +++ b/src/api/stats/ethereum/getAcrossApys.js @@ -3,17 +3,14 @@ import { fetchContract } from '../../rpc/client'; import getApyBreakdown from '../common/getApyBreakdown'; import { fetchPrice } from '../../../utils/fetchPrice'; import { ETH_CHAIN_ID } from '../../../constants'; -import AcceleratingDistributor from "../../../abis/ethereum/AcceleratingDistributor"; -import pools from "../../../data/ethereum/acrossPools.json"; +import AcceleratingDistributor from '../../../abis/ethereum/AcceleratingDistributor'; +import pools from '../../../data/ethereum/acrossPools.json'; -const Distributor = "0x9040e41eF5E8b281535a96D9a48aCb8cfaBD9a48"; -const url = "https://across.to/api/pools?token="; +const Distributor = '0x9040e41eF5E8b281535a96D9a48aCb8cfaBD9a48'; +const url = 'https://across.to/api/pools?token='; export const getAcrossApys = async () => { - const [tradingAprs, farmApys] = await Promise.all([ - getTradingAprs(), - getFarmApys(), - ]); + const [tradingAprs, farmApys] = await Promise.all([getTradingAprs(), getFarmApys()]); return getApyBreakdown(pools, tradingAprs, farmApys, 0.0006); }; @@ -26,7 +23,7 @@ const getTradingAprs = async () => { const response = await fetch(url + pool.underlying.address).then(res => res.json()); tradingAprs[pool.address.toLowerCase()] = new BigNumber(response.estimatedApy); } catch (e) { - console.log("Across url fetch error", e); + console.log('Across url fetch error', e); } } @@ -50,7 +47,11 @@ const getFarmApys = async () => { const pool = pools[i]; const price = await fetchPrice({ oracle: 'tokens', id: pool.underlying.symbol }); const totalStakedInUsd = staked[i].times(price).dividedBy(pool.decimals); - const apr = emissions[i].times(rewardPrice).dividedBy(1e18).times(31536000).dividedBy(totalStakedInUsd); + const apr = emissions[i] + .times(rewardPrice) + .dividedBy(1e18) + .times(31536000) + .dividedBy(totalStakedInUsd); farmApys.push(apr); } diff --git a/src/api/stats/ethereum/getAcrossPrices.js b/src/api/stats/ethereum/getAcrossPrices.js index df6e42a3a..e08504840 100644 --- a/src/api/stats/ethereum/getAcrossPrices.js +++ b/src/api/stats/ethereum/getAcrossPrices.js @@ -1,6 +1,6 @@ import BigNumber from 'bignumber.js'; const pools = require('../../../data/ethereum/acrossPools.json'); -const url = "https://across.to/api/pools?token="; +const url = 'https://across.to/api/pools?token='; const getAcrossPrices = async tokenPrices => { let prices = {}; @@ -13,7 +13,7 @@ const getAcrossPrices = async tokenPrices => { const price = exchangeRate.times(underlyingPrice).dividedBy(1e18).toNumber(); prices = { ...prices, [pool.name]: price }; } catch (e) { - console.log("Across url fetch error", e); + console.log('Across url fetch error', e); } } diff --git a/src/api/stats/kava/index.js b/src/api/stats/kava/index.js index 154fa2fce..e14b2b123 100644 --- a/src/api/stats/kava/index.js +++ b/src/api/stats/kava/index.js @@ -4,7 +4,13 @@ const getEquilibreApys = require('./getEquilibreApys'); const { getKinetixApys } = require('./getKinetixApys'); const getStargateKavaApys = require('./getStargateKavaApys'); -const getApys = [getCurveApys, getSushiLpApys, getEquilibreApys, getKinetixApys, getStargateKavaApys]; +const getApys = [ + getCurveApys, + getSushiLpApys, + getEquilibreApys, + getKinetixApys, + getStargateKavaApys, +]; const getKavaApys = async () => { const start = Date.now(); diff --git a/src/app.ts b/src/app.ts index c1ff2ed77..8e50b73c2 100644 --- a/src/app.ts +++ b/src/app.ts @@ -15,6 +15,7 @@ import { initTreasuryService } from './api/treasury/getTreasury'; import { initProposalsService } from './api/snapshot/getProposals'; import { initZapSwapService } from './api/zap/swap'; import { initValidatorPerformanceService } from './api/validators/validators'; +import { initArticlesService } from './api/articles/fetchArticlesData'; const Koa = require('koa'); const helmet = require('koa-helmet'); @@ -59,6 +60,7 @@ const start = async () => { initConfigService(); initProposalsService(); initTreasuryService(); + initArticlesService(); initZapSwapService(); app.listen(port); diff --git a/src/router.js b/src/router.js index 6ad993370..c9535d027 100644 --- a/src/router.js +++ b/src/router.js @@ -20,6 +20,7 @@ const { validatorPerformance } = require('./api/validators/index'); const { proxyOneInchSwap, proxyOneInchQuote } = require('./api/zap/proxy/one-inch'); const { proxyKyberSwap, proxyKyberQuote } = require('./api/zap/proxy/kyber'); const { zapSwapsSupport, zapSwapsSupportDebug } = require('./api/zap/swap/routes'); +const { getArticles, getLatestArticle } = require('./api/articles'); router.get('/validator-performance', validatorPerformance); @@ -74,6 +75,9 @@ router.get('/zap/providers/oneinch/:chainId/swap', proxyOneInchSwap); router.get('/zap/providers/kyber/:chainId/quote', proxyKyberQuote); router.post('/zap/providers/kyber/:chainId/swap', proxyKyberSwap); +router.get('/articles', getArticles); +router.get('/articles/latest', getLatestArticle); + router.get('/', noop); module.exports = router;