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

feat: Add a refresh method on pools that should efficiently refresh a… #583

Merged
merged 4 commits into from
Jul 5, 2024
Merged
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
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// yarn test:only ./src/modules/data/liquidity-gauges/multicall.spec.ts
import { expect } from 'chai';
import { JsonRpcProvider } from '@ethersproject/providers';
import { Zero } from '@ethersproject/constants';
Expand Down Expand Up @@ -65,7 +66,7 @@ describe('Liquidity gauge multicall', () => {
const fetcher = new LiquidityGaugesMulticallRepository(multicall, 1);

const gauges = new LiquidityGaugesSubgraphRepository(
'https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-gauges'
'https://api.studio.thegraph.com/query/75376/balancer-gauges/version/latest'
);

let gaugeAddresses: string[];
Expand Down
42 changes: 39 additions & 3 deletions balancer-js/src/modules/data/pool/subgraph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export class PoolsSubgraphRepository
public skip = 0;
private blockHeight: undefined | (() => Promise<number | undefined>);
private query: GraphQLQuery;
private isCustomQuery: boolean;

/**
* Repository with optional lazy loaded blockHeight
Expand All @@ -60,7 +61,7 @@ export class PoolsSubgraphRepository
},
},
};

this.isCustomQuery = !!options.query;
const args = Object.assign({}, options.query?.args || defaultArgs);
const attrs = Object.assign({}, options.query?.attrs || {});

Expand Down Expand Up @@ -121,8 +122,43 @@ export class PoolsSubgraphRepository
return pools.map((pool) => mapType(pool, this.chainId));
}

async find(id: string): Promise<Pool | undefined> {
return await this.findBy('id', id);
/**
* Find pool data for id
* @param id
* @param refresh If true will refetch from SG and update cache
* @returns
*/
async find(id: string, refresh = false): Promise<Pool | undefined> {
if (this.isCustomQuery) return await this.findBy('id', id);
// If we're not refreshing and the pool exists in caches then return
if (!refresh && this.pools) {
const cachedPool = (await this.pools).find((pool) => pool.id === id);
if (cachedPool) return cachedPool;
}

// Fetch pool data from SG, update cache and return
const logger = Logger.getInstance();

// SG fetch
logger.time(`fetching pool ${id}`);
const poolQuery = await this.client.Pool({ id });
logger.timeEnd(`fetching pool ${id}`);

if (!poolQuery.pool) return undefined;

const pool = mapType(poolQuery.pool, this.chainId);
// If the pool is already cached, replace it with the new one
logger.time(`updating cache`);
const pools = await this.pools;
if (pools) {
const index = pools.findIndex((p) => p.address === pool.address);
if (index !== -1) {
this.pools = Promise.resolve([...pools.splice(index, 1), pool]);
} else this.pools = Promise.resolve([...pools, pool]);
} else this.pools = Promise.resolve([pool]);
logger.timeEnd(`updating cache`);

return pool;
}

async findBy(param: PoolAttribute, value: string): Promise<Pool | undefined> {
Expand Down
2 changes: 1 addition & 1 deletion balancer-js/src/modules/data/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export * from './pool-shares/types';
export * from './gauge-shares/types';

export interface Findable<T, P = string, V = any> {
find: (id: string) => Promise<T | undefined>;
find: (id: string, refresh?: boolean) => Promise<T | undefined>;
findBy: (attribute: P, value: V) => Promise<T | undefined>;
}

Expand Down
3 changes: 2 additions & 1 deletion balancer-js/src/modules/pools/apr/apr.integration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ const usdStable =
const auraBALveBAL =
'0x3dd0843a028c86e0b760b1a76929d1c5ef93a2dd000200000000000000000249';

describe('APR tests', () => {
// APRs are offered via API now
describe.skip('APR tests', () => {
describe('pool with yield tokens', () => {
it('has tokenAprs', async () => {
const pool = await pools.find(ethStEth);
Expand Down
12 changes: 12 additions & 0 deletions balancer-js/src/modules/pools/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,18 @@ export class Pools implements Findable<PoolWithMethods> {
return this.repositories.pools;
}

/**
* Fetches new data from subgraph for pool
* (Will update PoolsSubgraphRepository cache)
* @param pool
* @returns
*/
async refresh(poolId: string): Promise<PoolWithMethods | undefined> {
const poolRefreshed = await this.repositories.pools.find(poolId, true);
if (!poolRefreshed) return poolRefreshed;
return Pools.wrap(poolRefreshed, this.networkConfig);
}

/**
* Calculates APR on any pool data
*
Expand Down
8 changes: 4 additions & 4 deletions balancer-js/src/modules/subgraph/codegen.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
overwrite: true
generates:
src/modules/subgraph/generated/balancer-subgraph-types.ts:
schema: ${BALANCER_SUBGRAPH_URL:https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-v2}
schema: ${BALANCER_SUBGRAPH_URL:https://api.studio.thegraph.com/query/75376/balancer-v2/version/latest}
documents: 'src/modules/subgraph/balancer-v2/**/*.graphql'
plugins:
- typescript
Expand All @@ -13,11 +13,11 @@ generates:
Bytes: string
BigDecimal: string
src/modules/subgraph/generated/balancer-subgraph-schema.graphql:
schema: ${BALANCER_SUBGRAPH_URL:https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-v2}
schema: ${BALANCER_SUBGRAPH_URL:https://api.studio.thegraph.com/query/75376/balancer-v2/version/latest}
plugins:
- schema-ast
src/modules/subgraph/generated/balancer-gauges.ts:
schema: ${BALANCER_GAUGES_URL:https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-gauges}
schema: ${BALANCER_GAUGES_URL:https://api.studio.thegraph.com/query/75376/balancer-gauges/version/latest}
documents: 'src/modules/subgraph/balancer-gauges/**/*.graphql'
plugins:
- typescript
Expand All @@ -31,7 +31,7 @@ generates:
namingConvention:
enumValues: keep
src/modules/subgraph/generated/balancer-gauges.graphql:
schema: ${BALANCER_GAUGES_URL:https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-gauges}
schema: ${BALANCER_GAUGES_URL:https://api.studio.thegraph.com/query/75376/balancer-gauges/version/latest}
plugins:
- schema-ast
hooks:
Expand Down
94 changes: 94 additions & 0 deletions balancer-js/src/modules/subgraph/generated/balancer-gauges.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ directive @entity on OBJECT
"""Defined a Subgraph ID for an object type"""
directive @subgraphId(id: String!) on OBJECT

enum Aggregation_interval {
day
hour
}

scalar BigDecimal

scalar BigInt
Expand Down Expand Up @@ -99,6 +104,30 @@ enum GaugeFactory_orderBy {
numGauges
}

type GaugeInjector {
""" GaugeInjector contract address """
id: ID!
}

input GaugeInjector_filter {
"""Filter for the block changed event."""
_change_block: BlockChangedFilter
and: [GaugeInjector_filter]
id: ID
id_gt: ID
id_gte: ID
id_in: [ID!]
id_lt: ID
id_lte: ID
id_not: ID
id_not_in: [ID!]
or: [GaugeInjector_filter]
}

enum GaugeInjector_orderBy {
id
}

type GaugeShare {
""" User's balance of gauge deposit tokens """
balance: BigDecimal!
Expand Down Expand Up @@ -1084,6 +1113,34 @@ type Query {
"""
subgraphError: _SubgraphErrorPolicy_! = deny
): GaugeFactory
gaugeInjector(
"""
The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted.
"""
block: Block_height
id: ID!

"""
Set to `allow` to receive data even if the subgraph has skipped over errors while syncing.
"""
subgraphError: _SubgraphErrorPolicy_! = deny
): GaugeInjector
gaugeInjectors(
"""
The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted.
"""
block: Block_height
first: Int = 100
orderBy: GaugeInjector_orderBy
orderDirection: OrderDirection
skip: Int = 0

"""
Set to `allow` to receive data even if the subgraph has skipped over errors while syncing.
"""
subgraphError: _SubgraphErrorPolicy_! = deny
where: GaugeInjector_filter
): [GaugeInjector!]!
gaugeShare(
"""
The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted.
Expand Down Expand Up @@ -1875,6 +1932,34 @@ type Subscription {
"""
subgraphError: _SubgraphErrorPolicy_! = deny
): GaugeFactory
gaugeInjector(
"""
The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted.
"""
block: Block_height
id: ID!

"""
Set to `allow` to receive data even if the subgraph has skipped over errors while syncing.
"""
subgraphError: _SubgraphErrorPolicy_! = deny
): GaugeInjector
gaugeInjectors(
"""
The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted.
"""
block: Block_height
first: Int = 100
orderBy: GaugeInjector_orderBy
orderDirection: OrderDirection
skip: Int = 0

"""
Set to `allow` to receive data even if the subgraph has skipped over errors while syncing.
"""
subgraphError: _SubgraphErrorPolicy_! = deny
where: GaugeInjector_filter
): [GaugeInjector!]!
gaugeShare(
"""
The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted.
Expand Down Expand Up @@ -2257,6 +2342,12 @@ type Subscription {
): [VotingEscrow!]!
}

"""
A string representation of microseconds UNIX timestamp (16 digits)

"""
scalar Timestamp

type User {
""" List of gauge the user has shares """
gaugeShares(first: Int = 100, orderBy: GaugeShare_orderBy, orderDirection: OrderDirection, skip: Int = 0, where: GaugeShare_filter): [GaugeShare!]
Expand Down Expand Up @@ -2504,6 +2595,9 @@ type _Block_ {
"""The block number"""
number: Int!

"""The hash of the parent block"""
parentHash: Bytes

"""Integer representation of the timestamp stored in blocks for the chain"""
timestamp: Int
}
Expand Down
Loading
Loading