Skip to content

Commit

Permalink
feat: support infinite range
Browse files Browse the repository at this point in the history
  • Loading branch information
jackmellis committed Nov 22, 2023
1 parent 4b41585 commit f0df1e7
Show file tree
Hide file tree
Showing 22 changed files with 115 additions and 54 deletions.
6 changes: 2 additions & 4 deletions lerna.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
{
"packages": [
"packages/*"
],
"version": "0.9.5",
"packages": ["packages/*"],
"version": "1.0.0",
"useWorkspaces": true,
"command": {
"publish": {
Expand Down
4 changes: 2 additions & 2 deletions packages/constants/src/addresses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ export const OPENSEA_COLLECTION = a(

/** Zap specifically for creating new vaults */
export const CREATE_VAULT_ZAP = {
[Network.Goerli]: a('0xFA7d98Ec2b046e636c45A0291F931b94a5a1CA59'),
[Network.Sepolia]: a('0x50f69c6556338965bf77C16ADb462Fdb5bE01C09'),
[Network.Goerli]: a('0xd58A1627bF1C2F8C724A9493A979C0369ab17AaB'),
[Network.Sepolia]: a('0xE7d5d168A8812Dcbe372A44a7632d6156f4DB13b'),
};

/** Perform buy/sell/swaps */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { Address, Vault } from '@nftx/types';
import { addressEqual, getChainConstant } from '@nftx/utils';
import { RESERVOIR_URL } from '@nftx/constants';
import fetchUserCollectionsReservoir from './reservoir';
import { fetchSubgraphVaults } from '../../vaults';
import fetchSubgraphVaults from '../../vaults/fetchSubgraphVaults';

type FetchUserCollectionsReservoir = typeof fetchUserCollectionsReservoir;

Expand Down
20 changes: 19 additions & 1 deletion packages/core/src/pools/fetchInventoryPool.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import config from '@nftx/config';
import fetchInventoryPools from './fetchInventoryPools';
import type { Provider, Vault } from '@nftx/types';
import type {
InventoryPosition,
LiquidityPool,
Provider,
Vault,
VaultFeeReceipt,
} from '@nftx/types';

type FetchInventoryPools = typeof fetchInventoryPools;

Expand All @@ -11,17 +17,29 @@ export const makeFetchInventoryPool =
network = config.network,
provider,
vaults,
feeReceipts,
liquidityPools,
positions,
}: {
network?: number;
vaultId: string;
provider: Provider;
vaults: Pick<Vault, 'vaultId' | 'id' | 'vTokenToEth' | 'createdAt'>[];
feeReceipts: Pick<VaultFeeReceipt, 'vaultId' | 'date' | 'amount'>[];
liquidityPools: Pick<
LiquidityPool,
'vaultId' | 'weeklyVolume' | 'dailyVolume'
>[];
positions: Pick<InventoryPosition, 'vaultId' | 'vToken' | 'vTokenValue'>[];
}) => {
const pools = await fetchInventoryPools({
network,
vaultIds: [vaultId],
provider,
vaults,
feeReceipts,
liquidityPools,
positions,
});
return pools?.[0];
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { InventoryPool, VaultFeeReceipt } from '@nftx/types';
import { Zero } from '@nftx/constants';

const calculatePeriodFees = (
receipts: VaultFeeReceipt[]
receipts: Pick<VaultFeeReceipt, 'date' | 'amount'>[]
): InventoryPool['periodFees'] => {
const periodFees: InventoryPool['periodFees'] = {
'1m': Zero,
Expand Down
43 changes: 20 additions & 23 deletions packages/core/src/pools/fetchInventoryPools/fetchInventoryPools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@ import type {
Address,
InventoryPool,
InventoryPosition,
LiquidityPool,
Provider,
Vault,
VaultFeeReceipt,
} from '@nftx/types';
import { fetchInventoryPositions } from '../../positions';
import filterVaults from './filterVaults';
import transformPool from './transformPool';
import fetchFeeReceipts from '../../vaults/fetchFeeReceipts';
import { getChainConstant, getContract } from '@nftx/utils';
import { INVENTORY_STAKING } from '@nftx/constants';
import { InventoryStaking } from '@nftx/abi';
Expand All @@ -21,39 +20,28 @@ const fetchInventoryPools = async ({
vaultIds,
provider,
vaults: allVaults,
feeReceipts: givenFeeReceipts,
positions: givenPositions,
feeReceipts,
positions,
liquidityPools: allLiquidityPools,
}: {
network?: number;
vaultAddresses?: Address[];
vaultIds?: string[];
provider: Provider;
vaults: Pick<Vault, 'vaultId' | 'id' | 'vTokenToEth' | 'createdAt'>[];
feeReceipts?: VaultFeeReceipt[];
positions?: InventoryPosition[];
feeReceipts: Pick<VaultFeeReceipt, 'date' | 'amount' | 'vaultId'>[];
positions: Pick<InventoryPosition, 'vaultId' | 'vToken' | 'vTokenValue'>[];
liquidityPools: Pick<
LiquidityPool,
'dailyVolume' | 'weeklyVolume' | 'vaultId'
>[];
}): Promise<InventoryPool[]> => {
const vaults = filterVaults({
vaults: allVaults,
vaultAddresses,
vaultIds,
});

const feeReceipts =
givenFeeReceipts ??
(await fetchFeeReceipts({
network,
vaultAddresses: vaults.map((v) => v.id),
}));

const positions =
givenPositions ??
(await fetchInventoryPositions({
network,
vaultIds: vaults.map((v) => v.vaultId),
vaults: allVaults,
provider,
}));

const inventoryContract = getContract({
provider,
address: getChainConstant(INVENTORY_STAKING, network),
Expand All @@ -66,8 +54,17 @@ const fetchInventoryPools = async ({
const receipts = feeReceipts.filter(
(receipt) => receipt.vaultId === vault.vaultId
);
const liquidityPools = allLiquidityPools.filter(
(pool) => pool.vaultId === vault.vaultId
);

return transformPool({ positions, vault, receipts, timelock });
return transformPool({
positions,
vault,
receipts,
timelock,
liquidityPools,
});
});
};

Expand Down
18 changes: 15 additions & 3 deletions packages/core/src/pools/fetchInventoryPools/transformPool.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type {
InventoryPool,
InventoryPosition,
LiquidityPool,
Vault,
VaultFeeReceipt,
} from '@nftx/types';
Expand All @@ -9,7 +10,7 @@ import calculateAprs from './calculateAprs';
import calculatePeriodFees from './calculatePeriodFees';

const calculatePoolValue = (
positions: InventoryPosition[],
positions: Pick<InventoryPosition, 'vaultId' | 'vToken' | 'vTokenValue'>[],
vaultId: string
) => {
type ValueTuple = [bigint, bigint, number];
Expand All @@ -36,18 +37,27 @@ const transformPool = ({
positions,
receipts,
timelock,
liquidityPools,
}: {
vault: Pick<Vault, 'id' | 'vaultId' | 'createdAt'>;
positions: InventoryPosition[];
receipts: VaultFeeReceipt[];
positions: Pick<InventoryPosition, 'vaultId' | 'vToken' | 'vTokenValue'>[];
receipts: Pick<VaultFeeReceipt, 'date' | 'amount'>[];
timelock: number;
liquidityPools: Pick<LiquidityPool, 'dailyVolume' | 'weeklyVolume'>[];
}): InventoryPool => {
const [vToken, vTokenValue, xNFTCount] = calculatePoolValue(
positions,
vault.vaultId
);
const periodFees = calculatePeriodFees(receipts);

let dailyVolume = Zero;
let weeklyVolume = Zero;
liquidityPools.forEach((pool) => {
dailyVolume += pool.dailyVolume;
weeklyVolume += pool.weeklyVolume;
});

return {
apr: calculateAprs({
createdAt: vault.createdAt,
Expand All @@ -62,6 +72,8 @@ const transformPool = ({
xNFTCount,
timelock,
totalPositions: positions.length,
dailyVolume,
weeklyVolume,
};
};

Expand Down
15 changes: 12 additions & 3 deletions packages/core/src/pools/fetchLiquidityPools/queryPoolData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ const queryPoolData = ({
s.activeLiquidity,
s.inputTokenBalances,
s.totalValueLockedETH,
s.openPositionCount,
s.fees((fee) => [fee.id, fee.feePercentage, fee.feeType]),
s.inputTokens((token) => [token.id, token.symbol, token.name]),
s.hourlySnapshots(
Expand All @@ -63,17 +64,25 @@ const queryPoolData = ({
.first(1000)
.orderBy('hour')
.orderDirection('desc')
.select((s) => [s.hourlyVolumeByTokenAmount, s.id])
.select((s) => [
s.hourlyVolumeByTokenAmount,
s.hourlyTotalRevenueETH,
s.id,
])
),
s.dailySnapshots(
q.liquidityPoolDailySnapshots
.where((w) => [w.timestamp.gte(`${oneWeekAgo}`)])
.first(1000)
.orderBy('day')
.orderDirection('desc')
.select((s) => [s.id, s.day, s.dailyVolumeByTokenAmount])
.select((s) => [
s.id,
s.day,
s.dailyVolumeByTokenAmount,
s.dailyTotalRevenueETH,
])
),
s.openPositionCount,
]);

return querySubgraph({
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/pools/fetchLiquidityPools/transformPool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ const transformPool = (
return total + value;
}, Zero);
const dailyRevenue = pool.hourlySnapshots.reduce((total, snapshot) => {
return total + BigInt(snapshot.hourlyTotalRevenueUSD ?? '0');
return total + BigInt(snapshot.hourlyTotalRevenueETH ?? '0');
}, Zero);
const weeklyVolume = pool.dailySnapshots.reduce((total, snapshot) => {
const value = BigInt(
Expand All @@ -86,7 +86,7 @@ const transformPool = (
return total + value;
}, Zero);
const weeklyRevenue = pool.dailySnapshots.reduce((total, snapshot) => {
return total + BigInt(snapshot.dailyTotalRevenueUSD ?? '0');
return total + BigInt(snapshot.dailyTotalRevenueETH ?? '0');
}, Zero);

const eth = tokens[isWeth0 ? 0 : 1].balance;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@ function updatePoolShares(positions: InventoryPosition[]) {
// First we need to get the total vToken for each pool
const poolVTokens: Record<string, bigint> = {};
positions.forEach((position) => {
const { vaultId: id, vToken } = position;
const current = poolVTokens[id] ?? Zero;
const { vaultId: poolId, vToken } = position;
const current = poolVTokens[poolId] ?? Zero;
const updated = current + vToken;

poolVTokens[position.vaultId] = updated;
});
// Then we need to work out the share of each position
positions.forEach((position) => {
const { vToken, vaultId: id } = position;
const total = poolVTokens[id];
const { vToken, vaultId: poolId } = position;
const total = poolVTokens[poolId];

if (!total) {
return;
Expand Down
9 changes: 8 additions & 1 deletion packages/core/src/univ3-helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export const getTickAtSqrtRatio = (
return 0;
}
const tick = TickMath.getTickAtSqrtRatio(bigintToJsbi(sqrtRatioX96));
const tickWithSpacing = Math.ceil(tick / tickSpacing) * tickSpacing;
const tickWithSpacing = getNearestValidTick(tick, tickSpacing);
return tickWithSpacing;
};

Expand All @@ -84,3 +84,10 @@ export const calculatePriceFromTick = (tick: number): bigint => {
return BigInt(Math.pow(TICK_PRICE_BASE, tickNum) * 1e18);
}
};

export const getNearestValidTick = (
tick: number,
tickSpacing: FeeTickSpacing
): number => {
return Math.ceil(tick / tickSpacing) * tickSpacing;
};
14 changes: 13 additions & 1 deletion packages/core/src/vaults/fetchVaults/fetchVaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import {
isMerkleVault,
fetchVTokenToEth,
} from '@nftx/utils';
import type { Address, Provider, Vault } from '@nftx/types';
import type { Address, Collection, Provider, Vault } from '@nftx/types';
import populateVaultPrices from './populateVaultPrices';
import { fetchCollection } from '../../collections';

const isVaultEnabled = (vault: Response['vaults'][0]) => {
// finalized or DAO vaults only
Expand Down Expand Up @@ -66,6 +67,8 @@ const fetchVaults = async ({
vaultIds: vaultData.map((v) => v.vaultId),
});

const collections: Record<string, Collection> = {};

const vaultPromises =
vaultData.map(async (x) => {
const y = {
Expand All @@ -86,11 +89,20 @@ const fetchVaults = async ({
vaultAddress: y.id,
});

let collection = collections[x.asset.id];
if (!collection) {
collection = collections[x.asset.id] = await fetchCollection({
network,
assetAddress: x.asset.id as Address,
});
}

const vault = transformVault({
globalFees,
vault: x,
merkleReference,
vTokenToEth,
collection,
});

const holdings = allHoldings.filter((h) => h.vaultId === x.vaultId);
Expand Down
4 changes: 4 additions & 0 deletions packages/core/src/vaults/fetchVaults/transformVault.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ const transformVault = ({
globalFees,
merkleReference,
vTokenToEth,
collection,
}: {
vault: Response['vaults'][0];
globalFees: Response['globals'][0]['fees'];
merkleReference?: string;
vTokenToEth: bigint;
collection: { slug: string };
}) => {
const rawFees = (x.usesFactoryFees && globalFees ? globalFees : x.fees) ?? {};
const fees: Vault['fees'] = mapObj(rawFees, (key, value) => {
Expand Down Expand Up @@ -43,6 +45,8 @@ const transformVault = ({
...x,
id: x.id as Address,
vaultId: `${x.vaultId}`,
slug: `${x.token.symbol}-${x.vaultId}`.toLowerCase(),
collectionSlug: (collection?.slug || x.asset.symbol).toLowerCase(),
asset: {
...x.asset,
id: x.asset.id as Address,
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/vaults/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export { default as fetchVaults } from './fetchVaults';
export { default as fetchSubgraphVaults } from './fetchSubgraphVaults';
export { default as fetchVault } from './fetchVault';
export { default as fetchVaultHoldings } from './fetchVaultHoldings';
export { default as fetchFeeReceipts } from './fetchFeeReceipts';
4 changes: 1 addition & 3 deletions packages/subgraph/src/__tests__/querySubgraph.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,7 @@ describe('error handling', () => {

const promise = querySubgraph({ url: 'https://nftx.io', query, fetch });

await expect(promise).rejects.toThrowError(
`Unexpected token '<', "<body><p>T"... is not valid JSON`
);
await expect(promise).rejects.toThrowError();
});
});

Expand Down
Loading

0 comments on commit f0df1e7

Please sign in to comment.