Skip to content
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

Update Integral to include SIZE pairs #560

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
25 changes: 25 additions & 0 deletions projects/integral/abis/fiveGetReserves.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"constant": true,
"inputs": [],
"name": "getReserves",
"outputs": [
{
"internalType": "uint112",
"name": "reserve0",
"type": "uint112"
},
{
"internalType": "uint112",
"name": "reserve1",
"type": "uint112"
},
{
"internalType": "uint32",
"name": "lastTimestamp",
"type": "uint32"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
}
20 changes: 20 additions & 0 deletions projects/integral/abis/sizeGetReserves.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"constant": true,
"inputs": [],
"name": "getReserves",
"outputs": [
{
"internalType": "uint112",
"name": "reserve0",
"type": "uint112"
},
{
"internalType": "uint112",
"name": "reserve1",
"type": "uint112"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
}
160 changes: 29 additions & 131 deletions projects/integral/index.js
Original file line number Diff line number Diff line change
@@ -1,145 +1,43 @@
/*==================================================
Modules
==================================================*/
const BigNumber = require('bignumber.js');
const sdk = require('../../sdk');

const TOKEN0_ABI = require('./abis/token0.json');
const TOKEN1_ABI = require('./abis/token1.json');
const GET_RESERVES_ABI = require('./abis/getReserves.json');

const START_BLOCK = 12108732;
const FACTORY = '0x673662e97b05e001816c380ba5a628d2e29f55d1';

async function tvl(_, block) {
const pairs = await getPairs(block);
const reserves = await getReserves(block, pairs);
const balances = await getBalances(pairs, reserves);

return balances;
}

async function getSupportedTokens() {
const tokens = await sdk.api.util.tokenList();

return new Set(tokens.map(({ contract }) => contract));
}

async function getPairAddresses(block) {
const logs = await sdk.api.util.getLogs({
keys: [],
toBlock: block,
target: FACTORY,
fromBlock: START_BLOCK,
topic: 'PairCreated(address,address,address,uint256)',
});

return logs.output
.map(log => typeof log === 'string' ? log : `0x${log.data.slice(64 - 40 + 2, 64 + 2)}`)
.map(pairAddress => pairAddress.toLowerCase());
}

async function getPairs(block) {
const supportedTokens = await getSupportedTokens();
const pairAddresses = await getPairAddresses(block);
const [token0Addresses, token1Addresses] = await getTokenAddresses(block, pairAddresses);
const pairs = constructPairs(supportedTokens, token0Addresses, token1Addresses);

return pairs;
}

async function getTokenAddresses(block, pairAddresses) {
const [token0Addresses, token1Addresses] = await Promise.all([
sdk.api.abi.multiCall({
abi: TOKEN0_ABI,
calls: pairAddresses.map(pairAddress => ({
target: pairAddress,
})),
block,
}),
sdk.api.abi.multiCall({
abi: TOKEN1_ABI,
calls: pairAddresses.map(pairAddress => ({
target: pairAddress,
})),
block,
}),
const TVL = require('./utils');

/*==================================================
TVL
==================================================*/
async function tvl(timestamp, block) {
const [five, size] = await Promise.all([
TVL(timestamp, block, 'five'),
TVL(timestamp, block, 'size')
]);

return [token0Addresses.output, token1Addresses.output];
}

async function constructPairs(supportedTokens, token0Addresses, token1Addresses) {
const pairs = {};
const tokenAddresses = new Set(Object.keys(five).concat(Object.keys(size)));

token0Addresses.forEach((token0Address) => {
if (token0Address.success) {
const tokenAddress = token0Address.output.toLowerCase();
if (supportedTokens.has(tokenAddress)) {
const pairAddress = token0Address.input.target.toLowerCase();
pairs[pairAddress] = {
token0Address: tokenAddress,
}
}
}
});

token1Addresses.forEach((token1Address) => {
if (token1Address.success) {
const tokenAddress = token1Address.output.toLowerCase();
if (supportedTokens.has(tokenAddress)) {
const pairAddress = token1Address.input.target.toLowerCase();
pairs[pairAddress] = {
...(pairs[pairAddress] || {}),
token1Address: tokenAddress,
}
}
}
});

return pairs;
}
const balances = (
Array
.from(tokenAddresses)
.reduce((accumulator, tokenAddress) => {
const fiveBalance = new BigNumber(five[tokenAddress] || '0');
const sizeBalance = new BigNumber(size[tokenAddress] || '0');
accumulator[tokenAddress] = fiveBalance.plus(sizeBalance).toFixed();

async function getReserves(block, pairs) {
const reserves = await sdk.api.abi.multiCall({
abi: GET_RESERVES_ABI,
calls: Object.keys(pairs).map((pairAddress) => ({
target: pairAddress,
})),
block,
});
return accumulator;
}, {})
);

return reserves.output;
}

async function getBalances(pairs, reserves) {
return reserves.reduce((memo, reserve) => {
if (reserve.success) {
const pairAddress = reserve.input.target.toLowerCase();
const pair = pairs[pairAddress] || {};

if (pair.token0Address) {
const reserve0 = new BigNumber(reserve.output['0']);
if (!reserve0.isZero()) {
const existingBalance = new BigNumber(memo[pair.token0Address] || '0');
memo[pair.token0Address] = existingBalance.plus(reserve0).toFixed()
}
}

if (pair.token1Address) {
const reserve1 = new BigNumber(reserve.output['1']);
if (!reserve1.isZero()) {
const existingBalance = new BigNumber(memo[pair.token1Address] || '0');
memo[pair.token1Address] = existingBalance.plus(reserve1).toFixed()
}
}
}

return memo
}, {});
return balances;
}

/*==================================================
Exports
==================================================*/
module.exports = {
name: 'Integral',
token: null,
category: 'DEXes',
token: 'ITGR',
category: 'dexes',
start: 1617031800, // 03/29/2021 @ 2:30PM (UTC)
tvl,
};
153 changes: 153 additions & 0 deletions projects/integral/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/*==================================================
Modules
==================================================*/
const BigNumber = require('bignumber.js');
const sdk = require('../../sdk');

const TOKEN0_ABI = require('./abis/token0.json');
const TOKEN1_ABI = require('./abis/token1.json');
const FIVE_GET_RESERVES_ABI = require('./abis/fiveGetReserves.json');
const SIZE_GET_RESERVES_ABI = require('./abis/sizeGetReserves.json');

/*==================================================
Settings
==================================================*/
const FIVE_START_BLOCK = 12108732;
const FIVE_FACTORY = '0x673662e97b05e001816c380ba5a628d2e29f55d1';
const SIZE_START_BLOCK = 14422957;
const SIZE_FACTORY = '0xC480b33eE5229DE3FbDFAD1D2DCD3F3BAD0C56c6';

const Product = {
five: 'five',
size: 'size',
}
/*==================================================
TVL
==================================================*/
module.exports = async function tvl(_, block, product) {
const pairs = await getPairs(block, product);
const reserves = await getReserves(block, pairs, product);
const balances = getBalances(pairs, reserves);

return balances;
}

async function getSupportedTokens() {
const tokens = await sdk.api.util.tokenList();

return new Set(tokens.map(({ contract }) => contract));
}

async function getPairAddresses(block, product) {
const logs = await sdk.api.util.getLogs({
keys: [],
toBlock: block,
target: product == Product.five ? FIVE_FACTORY : SIZE_FACTORY,
fromBlock: product == Product.five ? FIVE_START_BLOCK : SIZE_START_BLOCK,
topic: 'PairCreated(address,address,address,uint256)',
});

return logs.output
.map(log => typeof log === 'string' ? log : `0x${log.data.slice(64 - 40 + 2, 64 + 2)}`)
.map(pairAddress => pairAddress.toLowerCase());
}

async function getPairs(block, product) {
const supportedTokens = await getSupportedTokens();
const pairAddresses = await getPairAddresses(block, product);
const [token0Addresses, token1Addresses] = await getTokenAddresses(block, pairAddresses);
const pairs = constructPairs(supportedTokens, token0Addresses, token1Addresses);

return pairs;
}

async function getTokenAddresses(block, pairAddresses) {
const [token0Addresses, token1Addresses] = await Promise.all([
sdk.api.abi.multiCall({
abi: TOKEN0_ABI,
calls: pairAddresses.map(pairAddress => ({
target: pairAddress,
})),
block,
}),
sdk.api.abi.multiCall({
abi: TOKEN1_ABI,
calls: pairAddresses.map(pairAddress => ({
target: pairAddress,
})),
block,
}),
]);

return [token0Addresses.output, token1Addresses.output];
}

async function constructPairs(supportedTokens, token0Addresses, token1Addresses) {
const pairs = {};

token0Addresses.forEach((token0Address) => {
if (token0Address.success) {
const tokenAddress = token0Address.output.toLowerCase();
if (supportedTokens.has(tokenAddress)) {
const pairAddress = token0Address.input.target.toLowerCase();
pairs[pairAddress] = {
token0Address: tokenAddress,
}
}
}
});

token1Addresses.forEach((token1Address) => {
if (token1Address.success) {
const tokenAddress = token1Address.output.toLowerCase();
if (supportedTokens.has(tokenAddress)) {
const pairAddress = token1Address.input.target.toLowerCase();
pairs[pairAddress] = {
...(pairs[pairAddress] || {}),
token1Address: tokenAddress,
}
}
}
});

return pairs;
}

async function getReserves(block, pairs, product) {
const reserves = await sdk.api.abi.multiCall({
abi: product == Product.five ? FIVE_GET_RESERVES_ABI : SIZE_GET_RESERVES_ABI,
calls: Object.keys(pairs).map((pairAddress) => ({
target: pairAddress,
})),
block,
});

return reserves.output;
}

async function getBalances(pairs, reserves) {
return reserves.reduce((memo, reserve) => {
if (reserve.success) {
const pairAddress = reserve.input.target.toLowerCase();
const pair = pairs[pairAddress] || {};

if (pair.token0Address) {
const reserve0 = new BigNumber(reserve.output['0']);
if (!reserve0.isZero()) {
const existingBalance = new BigNumber(memo[pair.token0Address] || '0');
memo[pair.token0Address] = existingBalance.plus(reserve0).toFixed()
}
}

if (pair.token1Address) {
const reserve1 = new BigNumber(reserve.output['1']);
if (!reserve1.isZero()) {
const existingBalance = new BigNumber(memo[pair.token1Address] || '0');
memo[pair.token1Address] = existingBalance.plus(reserve1).toFixed()
}
}
}

return memo
}, {});
}