Skip to content

Commit

Permalink
Merge pull request #382 from balancer/develop
Browse files Browse the repository at this point in the history
Release 4.1.1-beta.8
  • Loading branch information
John Grant authored Apr 13, 2023
2 parents 2eedb66 + 11b7d36 commit 768db76
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 30 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@balancer-labs/sor",
"version": "4.1.1-beta.7",
"version": "4.1.1-beta.8",
"license": "GPL-3.0-only",
"main": "dist/index.js",
"module": "dist/index.esm.js",
Expand Down
14 changes: 11 additions & 3 deletions src/poolCacher.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import cloneDeep from 'lodash.clonedeep';
import { PoolDataService, SubgraphPoolBase, SubgraphToken } from './types';
import {
PoolDataService,
SubgraphPoolBase,
SubgraphToken,
GraphQLArgs,
} from './types';

export class PoolCacher {
private pools: SubgraphPoolBase[] = [];
Expand Down Expand Up @@ -37,10 +42,13 @@ export class PoolCacher {

/*
* Saves updated pools data to internal cache.
*
* @param {GraphQLArgs} queryArgs - Optional query arguments to pass to pool data service.
* @returns {boolean} True if pools fetched successfully, False if not.
*/
public async fetchPools(): Promise<boolean> {
public async fetchPools(queryArgs?: GraphQLArgs): Promise<boolean> {
try {
this.pools = await this.poolDataService.getPools();
this.pools = await this.poolDataService.getPools(queryArgs);
this._finishedFetching = true;
return true;
} catch (err) {
Expand Down
11 changes: 7 additions & 4 deletions src/pools/composableStable/composableStablePool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,12 @@ export class ComposableStablePool extends PhantomStablePool {
_calcTokensOutGivenExactBptIn(bptAmountIn: BigNumber): BigNumber[] {
// balances and amounts must be normalized to 1e18 fixed point - e.g. 1USDC => 1e18 not 1e6
// takes price rate into account
const balancesNormalised = this.tokens
.filter((t) => !isSameAddress(t.address, this.address))
.map((t) => normaliseBalance(t));
const tokensWithoutBpt = this.tokens.filter(
(t) => !isSameAddress(t.address, this.address)
);
const balancesNormalised = tokensWithoutBpt.map((t) =>
normaliseBalance(t)
);
try {
const amountsOutNormalised = _calcTokensOutGivenExactBptIn(
balancesNormalised,
Expand All @@ -194,7 +197,7 @@ export class ComposableStablePool extends PhantomStablePool {
);
// We want to return denormalised amounts. e.g. 1USDC => 1e6 not 1e18
const amountsOut = amountsOutNormalised.map((a, i) =>
denormaliseAmount(a, this.tokens[i])
denormaliseAmount(a, tokensWithoutBpt[i])
);
return amountsOut.map((a) => BigNumber.from(a));
} catch (err) {
Expand Down
22 changes: 21 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ export interface TokenPriceService {
}

export interface PoolDataService {
getPools(): Promise<SubgraphPoolBase[]>;
getPools(query?: GraphQLArgs): Promise<SubgraphPoolBase[]>;
}

export type FundManagement = {
Expand All @@ -279,3 +279,23 @@ export type FundManagement = {
fromInternalBalance: boolean;
toInternalBalance: boolean;
};

type GraphQLFilterOperator = 'gt' | 'lt' | 'eq' | 'in' | 'not_in' | 'contains';

type GraphQLFilter = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[operator in GraphQLFilterOperator]?: any;
};

export interface GraphQLArgs {
chainId?: number;
first?: number;
skip?: number;
nextToken?: string;
orderBy?: string;
orderDirection?: string;
block?: {
number?: number;
};
where?: Record<string, GraphQLFilter>;
}
102 changes: 83 additions & 19 deletions test/ComposableStable.integration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ import { expect } from 'chai';
import { closeTo } from './lib/testHelpers';
import { ComposableStablePool } from '../src/pools/composableStable/composableStablePool';
import { setUp, queryJoin, querySingleTokenExit } from './testScripts/utils';
import { queryExit } from './testScripts/utils';

dotenv.config();

let sor: SOR;
const networkId = Network.MAINNET;
const jsonRpcUrl = 'https://mainnet.infura.io/v3/' + process.env.INFURA;
const rpcUrl = 'http://127.0.0.1:8545';
const blockNumber = 16447247;
const blockNumber = 16990000;
const provider = new JsonRpcProvider(rpcUrl, networkId);
const vault = Vault__factory.connect(vaultAddr, provider);
const bbausdt = ADDRESSES[networkId].bbausdt.address;
Expand All @@ -31,42 +32,42 @@ const funds = {
toInternalBalance: false,
};

// bbausd
// bbausd @ 16990000
const testPool: SubgraphPoolBase = {
id: '0xa13a9247ea42d743238089903570127dda72fe4400000000000000000000035d',
address: '0xa13a9247ea42d743238089903570127dda72fe44',
poolType: 'ComposableStable',
swapFee: '0.00001',
swapEnabled: true,
totalShares: '64596326.424409523591670321',
totalShares: '44932059.875228056705169881',
tokens: [
{
address: '0x2f4eb100552ef93840d5adc30560e5513dfffacb',
balance: '19886024.363497322713220006',
balance: '11320218.4542653482060962',
decimals: 18,
weight: null,
priceRate: '1.005556566563028326',
priceRate: '1.008907049994305145',
},
{
address: '0x82698aecc9e28e9bb27608bd52cf57f704bd1b83',
balance: '22661432.733475610301640733',
balance: '16511760.493782176032607228',
decimals: 18,
weight: null,
priceRate: '1.001701405807798182',
priceRate: '1.003255006836090536',
},
{
address: '0xa13a9247ea42d743238089903570127dda72fe44',
balance: '2596148352278451.368726075585090202',
balance: '2596148361607118.360575356706891466',
decimals: 18,
weight: null,
priceRate: '1',
},
{
address: '0xae37d54ae477268b9997d4161b96b8200755935c',
balance: '22025447.315652715921042479',
balance: '17104601.130227607634969653',
decimals: 18,
weight: null,
priceRate: '1.001877219965246124',
priceRate: '1.002588724317365782',
},
],
tokensList: [
Expand All @@ -77,6 +78,52 @@ const testPool: SubgraphPoolBase = {
],
amp: '1472',
};
// wstETH-rETH-sfrxETH @ 16990000
const testPool1: SubgraphPoolBase = {
id: '0x5aee1e99fe86960377de9f88689616916d5dcabe000000000000000000000467',
address: '0x5aee1e99fe86960377de9f88689616916d5dcabe',
poolType: 'ComposableStable',
swapFee: '0.0004',
swapEnabled: true,
totalShares: '21247.444534559295227932',
tokens: [
{
address: '0x5aee1e99fe86960377de9f88689616916d5dcabe',
balance: '2596148429265403.127032833448903301',
decimals: 18,
weight: null,
priceRate: '1',
},
{
address: '0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0',
balance: '7051.391254798909416156',
decimals: 18,
weight: null,
priceRate: '1.117688527755347286',
},
{
address: '0xac3e018457b222d93114458476f3e3416abbe38f',
balance: '7252.664978235535296556',
decimals: 18,
weight: null,
priceRate: '1.032699398192610799',
},
{
address: '0xae78736cd615f374d3085123a210448e74fc6393',
balance: '5625.21808010082984482',
decimals: 18,
weight: null,
priceRate: '1.065201248378856766',
},
],
tokensList: [
'0x5aee1e99fe86960377de9f88689616916d5dcabe',
'0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0',
'0xac3e018457b222d93114458476f3e3416abbe38f',
'0xae78736cd615f374d3085123a210448e74fc6393',
],
amp: '105',
};

describe('ComposableStable', () => {
// Setup chain
Expand All @@ -86,7 +133,7 @@ describe('ComposableStable', () => {
sor = await setUp(
networkId,
provider,
[testPool],
[testPool, testPool1],
jsonRpcUrl as string,
blockNumber
);
Expand Down Expand Up @@ -362,14 +409,31 @@ describe('ComposableStable', () => {
// });
// }).timeout(20000);

// ComposableStable V1 does not have this functionality but V2 does
// it('BPT>tokens', async () => {
// const bptIn = parseFixed('77', 18);
// const pools = sor.getPools();
// const pool = ComposableStablePool.fromPool(pools[0]);
// const amountOut = pool._calcTokensOutGivenExactBptIn(bptIn);
// console.log(amountOut.toString());
// }).timeout(10000);
it('BPT>tokens', async () => {
const bptInEvm = parseFixed('10', 18);
const pools = sor.getPools();
const pool = ComposableStablePool.fromPool(pools[1]);
const amountsOutEvm =
pool._calcTokensOutGivenExactBptIn(bptInEvm);

const { bptIn, amountsOut } = await queryExit(
provider,
pool.id,
pool.tokensList,
bptInEvm.toString(),
true
);
const amountsOutWithoutBpt = [...amountsOut];
amountsOutWithoutBpt.splice(
pool.tokensList.indexOf(pool.address),
1
); // remove BPT amount

expect(bptIn.toString()).to.eq(bptInEvm.toString());
amountsOutEvm.forEach((a, i) => {
closeTo(a, amountsOutWithoutBpt[i], 1e14); // accuracy of 1e4 - is not an exact match due to protocol fees not being considered on calculations
});
}).timeout(10000);
});
});
});
5 changes: 3 additions & 2 deletions test/testScripts/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -359,15 +359,16 @@ export async function queryExit(
provider: JsonRpcProvider,
poolId: string,
assets: string[],
bptIn: string
bptIn: string,
isComposablePool = false
): Promise<
[BigNumber, BigNumber[]] & { bptIn: BigNumber; amountsOut: BigNumber[] }
> {
const helpers = BalancerHelpers__factory.connect(
ADDRESSES[provider.network.chainId].balancerHelpers,
provider
);
const EXACT_BPT_IN_FOR_TOKENS_OUT = 1; // Alternative is: BPT_IN_FOR_EXACT_TOKENS_OUT (No proportional)
const EXACT_BPT_IN_FOR_TOKENS_OUT = isComposablePool ? 2 : 1; // Alternative is: BPT_IN_FOR_EXACT_TOKENS_OUT (No proportional)
const abi = ['uint256', 'uint256'];

const data = [EXACT_BPT_IN_FOR_TOKENS_OUT, bptIn];
Expand Down

0 comments on commit 768db76

Please sign in to comment.