From dde08b5280afab01541ae13b462764f723b3a06e Mon Sep 17 00:00:00 2001 From: Soil King <157099073+soilking@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:50:45 -0700 Subject: [PATCH] subgraph: gauge tests --- .../tests/SeedGauge.test.ts | 164 ++++++++++++++++++ .../tests/event-mocking/Field.ts | 21 ++- .../tests/event-mocking/SeedGauge.ts | 124 +++++++++++++ .../tests/event-mocking/Whitelist.ts | 46 +++++ .../tests/event-mocking/Prices.ts | 127 ++++++++++++++ 5 files changed, 479 insertions(+), 3 deletions(-) create mode 100644 projects/subgraph-beanstalk/tests/SeedGauge.test.ts create mode 100644 projects/subgraph-beanstalk/tests/event-mocking/SeedGauge.ts create mode 100644 projects/subgraph-beanstalk/tests/event-mocking/Whitelist.ts create mode 100644 projects/subgraph-core/tests/event-mocking/Prices.ts diff --git a/projects/subgraph-beanstalk/tests/SeedGauge.test.ts b/projects/subgraph-beanstalk/tests/SeedGauge.test.ts new file mode 100644 index 0000000000..a62abd2a49 --- /dev/null +++ b/projects/subgraph-beanstalk/tests/SeedGauge.test.ts @@ -0,0 +1,164 @@ +import { afterEach, assert, clearStore, describe, test } from "matchstick-as/assembly/index"; +import { log } from "matchstick-as/assembly/log"; +import { BigInt } from "@graphprotocol/graph-ts"; + +import { + handleTemperatureChange, + handleBeanToMaxLpGpPerBdvRatioChange, + handleGaugePointChange, + handleUpdateAverageStalkPerBdvPerSeason, + handleFarmerGerminatingStalkBalanceChanged, + handleTotalGerminatingBalanceChanged, + handleWhitelistToken_BIP42, + handleUpdateGaugeSettings +} from "../src/GaugeHandler"; + +import { BEAN_ERC20, BEANSTALK } from "../../subgraph-core/utils/Constants"; +import { + createBeanToMaxLpGpPerBdvRatioChangeEvent, + createFarmerGerminatingStalkBalanceChangedEvent, + createGaugePointChangeEvent, + createTotalGerminatingBalanceChangedEvent, + createUpdateAverageStalkPerBdvPerSeasonEvent, + createUpdateGaugeSettingsEvent +} from "./event-mocking/SeedGauge"; +import { createWhitelistTokenEventBIP42 } from "./event-mocking/Whitelist"; +import { createTemperatureChangeEvent } from "./event-mocking/Field"; +import { simpleMockPrice } from "../../subgraph-core/tests/event-mocking/Prices"; + +const ANVIL_ADDR_1 = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266".toLowerCase(); + +const ratioDecimals = BigInt.fromU32(10).pow(18); + +describe("Seed Gauge", () => { + afterEach(() => { + log.debug("clearing the store", []); + clearStore(); + }); + + describe("Renamed Temperature Event", () => { + test("Renamed Temperature Event", () => { + simpleMockPrice(1, 1); + + // Temperature inits to 1 + handleTemperatureChange(createTemperatureChangeEvent(BigInt.fromU32(1), BigInt.fromU32(15), 5)); + assert.fieldEquals("Field", BEANSTALK.toHexString(), "temperature", "6"); + assert.fieldEquals("FieldHourlySnapshot", BEANSTALK.toHexString() + "-1", "caseId", "15"); + handleTemperatureChange(createTemperatureChangeEvent(BigInt.fromU32(2), BigInt.fromU32(25), 2)); + assert.fieldEquals("Field", BEANSTALK.toHexString(), "temperature", "8"); + assert.fieldEquals("FieldHourlySnapshot", BEANSTALK.toHexString() + "-2", "caseId", "25"); + }); + }); + + describe("Seasonal Adjustments", () => { + test("event: BeanToMaxLpGpPerBdvRatioChange (initialization)", () => { + const initialRatio = BigInt.fromI32(66).times(ratioDecimals); + handleBeanToMaxLpGpPerBdvRatioChange( + createBeanToMaxLpGpPerBdvRatioChangeEvent(BigInt.fromU32(20000), BigInt.fromU32(10), initialRatio) + ); + assert.fieldEquals("Silo", BEANSTALK.toHexString(), "beanToMaxLpGpPerBdvRatio", initialRatio.toString()); + assert.fieldEquals("SiloHourlySnapshot", BEANSTALK.toHexString() + "-20000", "caseId", "10"); + }); + + test("event: BeanToMaxLpGpPerBdvRatioChange (adjustment)", () => { + const initialRatio = BigInt.fromI32(66).times(ratioDecimals); + handleBeanToMaxLpGpPerBdvRatioChange( + createBeanToMaxLpGpPerBdvRatioChangeEvent(BigInt.fromU32(20000), BigInt.fromU32(10), initialRatio) + ); + + const adjustment1 = BigInt.fromI32(2).times(ratioDecimals); + const adjustment2 = BigInt.fromI32(-5).times(ratioDecimals); + handleBeanToMaxLpGpPerBdvRatioChange( + createBeanToMaxLpGpPerBdvRatioChangeEvent(BigInt.fromU32(20001), BigInt.fromU32(10), adjustment1) + ); + assert.fieldEquals("Silo", BEANSTALK.toHexString(), "beanToMaxLpGpPerBdvRatio", initialRatio.plus(adjustment1).toString()); + handleBeanToMaxLpGpPerBdvRatioChange( + createBeanToMaxLpGpPerBdvRatioChangeEvent(BigInt.fromU32(20002), BigInt.fromU32(10), adjustment2) + ); + assert.fieldEquals( + "Silo", + BEANSTALK.toHexString(), + "beanToMaxLpGpPerBdvRatio", + initialRatio.plus(adjustment1).plus(adjustment2).toString() + ); + }); + + test("event: GaugePointChange", () => { + handleGaugePointChange(createGaugePointChangeEvent(BigInt.fromU32(20000), BEAN_ERC20.toHexString(), BigInt.fromU32(12345))); + assert.fieldEquals("WhitelistTokenSetting", BEAN_ERC20.toHexString(), "gaugePoints", "12345"); + }); + + test("event: UpdateAverageStalkPerBdvPerSeason", () => { + handleUpdateAverageStalkPerBdvPerSeason(createUpdateAverageStalkPerBdvPerSeasonEvent(BigInt.fromU32(3456))); + assert.fieldEquals("Silo", BEANSTALK.toHexString(), "grownStalkPerBdvPerSeason", "3456"); + }); + }); + + describe("Germinating Stalk", () => { + test("event: FarmerGerminatingStalkBalanceChanged", () => { + const initialGerminating = BigInt.fromI32(123456); + handleFarmerGerminatingStalkBalanceChanged(createFarmerGerminatingStalkBalanceChangedEvent(ANVIL_ADDR_1, initialGerminating)); + assert.fieldEquals("Silo", ANVIL_ADDR_1, "germinatingStalk", initialGerminating.toString()); + const adjustment = BigInt.fromI32(-5000); + handleFarmerGerminatingStalkBalanceChanged(createFarmerGerminatingStalkBalanceChangedEvent(ANVIL_ADDR_1, adjustment)); + assert.fieldEquals("Silo", ANVIL_ADDR_1, "germinatingStalk", initialGerminating.plus(adjustment).toString()); + }); + + // TODO: germinating by asset? + test("event: TotalGerminatingBalanceChanged", () => { + const initialGerminating = BigInt.fromI32(123456789); + handleTotalGerminatingBalanceChanged( + createTotalGerminatingBalanceChangedEvent(BigInt.fromU32(20000), BEAN_ERC20.toHexString(), initialGerminating, initialGerminating) + ); + assert.fieldEquals("Silo", BEANSTALK.toHexString(), "germinatingStalk", initialGerminating.toString()); + const adjustment = BigInt.fromI32(-8000000); + handleTotalGerminatingBalanceChanged( + createTotalGerminatingBalanceChangedEvent(BigInt.fromU32(20001), BEAN_ERC20.toHexString(), adjustment, adjustment) + ); + assert.fieldEquals("Silo", BEANSTALK.toHexString(), "germinatingStalk", initialGerminating.plus(adjustment).toString()); + }); + }); + + describe("Owner Configuration", () => { + test("event: WhitelistToken", () => { + handleWhitelistToken_BIP42( + createWhitelistTokenEventBIP42( + BEAN_ERC20.toHexString(), + "0x12345678", + BigInt.fromU64(35000000000), + BigInt.fromU64(10000000000), + "0xabcdabcd", + "0xdefdef1a", + BigInt.fromU32(12345), + BigInt.fromU32(66).times(ratioDecimals) + ) + ); + assert.fieldEquals("WhitelistTokenSetting", BEAN_ERC20.toHexString(), "selector", "0x12345678"); + assert.fieldEquals("WhitelistTokenSetting", BEAN_ERC20.toHexString(), "stalkEarnedPerSeason", BigInt.fromU64(35000000000).toString()); + assert.fieldEquals("WhitelistTokenSetting", BEAN_ERC20.toHexString(), "stalkIssuedPerBdv", BigInt.fromU64(10000000000).toString()); + assert.fieldEquals("WhitelistTokenSetting", BEAN_ERC20.toHexString(), "gpSelector", "0xabcdabcd"); + assert.fieldEquals("WhitelistTokenSetting", BEAN_ERC20.toHexString(), "lwSelector", "0xdefdef1a"); + assert.fieldEquals("WhitelistTokenSetting", BEAN_ERC20.toHexString(), "gaugePoints", BigInt.fromU32(12345).toString()); + assert.fieldEquals( + "WhitelistTokenSetting", + BEAN_ERC20.toHexString(), + "optimalPercentDepositedBdv", + BigInt.fromU32(66).times(ratioDecimals).toString() + ); + }); + + test("event: UpdateGaugeSettings", () => { + handleUpdateGaugeSettings( + createUpdateGaugeSettingsEvent(BEAN_ERC20.toHexString(), "0x12341234", "0xabcabcde", BigInt.fromU32(66).times(ratioDecimals)) + ); + assert.fieldEquals("WhitelistTokenSetting", BEAN_ERC20.toHexString(), "gpSelector", "0x12341234"); + assert.fieldEquals("WhitelistTokenSetting", BEAN_ERC20.toHexString(), "lwSelector", "0xabcabcde"); + assert.fieldEquals( + "WhitelistTokenSetting", + BEAN_ERC20.toHexString(), + "optimalPercentDepositedBdv", + BigInt.fromU32(66).times(ratioDecimals).toString() + ); + }); + }); +}); diff --git a/projects/subgraph-beanstalk/tests/event-mocking/Field.ts b/projects/subgraph-beanstalk/tests/event-mocking/Field.ts index c414d34cae..935944f00f 100644 --- a/projects/subgraph-beanstalk/tests/event-mocking/Field.ts +++ b/projects/subgraph-beanstalk/tests/event-mocking/Field.ts @@ -1,10 +1,8 @@ import { Address, BigInt, Bytes, ethereum } from "@graphprotocol/graph-ts"; import { newMockEvent } from "matchstick-as/assembly/index"; import { Sow, PlotTransfer } from "../../generated/Field/Beanstalk"; +import { TemperatureChange } from "../../generated/BIP42-SeedGauge/Beanstalk"; -import { AddDeposit, RemoveDeposit, RemoveDeposits } from "../../generated/Silo-Replanted/Beanstalk"; -import { handleAddDeposit } from "../../src/SiloHandler"; -import { BEAN_DECIMALS } from "../../../subgraph-core/utils/Constants"; import { BEANSTALK } from "../../../subgraph-core/utils/Constants"; // Default mock to include beanstalk address @@ -15,6 +13,23 @@ const mockBeanstalkEvent = (): ethereum.Event => { }; export function createWeatherChangeEvent(season: BigInt, caseID: BigInt, change: i32): void {} + +// BIP42 renamed +export function createTemperatureChangeEvent(season: BigInt, caseId: BigInt, absChange: i32): TemperatureChange { + let event = changetype(mockBeanstalkEvent()); + event.parameters = new Array(); + + let param1 = new ethereum.EventParam("season", ethereum.Value.fromUnsignedBigInt(season)); + let param2 = new ethereum.EventParam("caseId", ethereum.Value.fromUnsignedBigInt(caseId)); + let param3 = new ethereum.EventParam("absChange", ethereum.Value.fromI32(absChange)); + + event.parameters.push(param1); + event.parameters.push(param2); + event.parameters.push(param3); + + return event as TemperatureChange; +} + export function createSowEvent(account: string, index: BigInt, beans: BigInt, pods: BigInt): Sow { let event = changetype(mockBeanstalkEvent()); event.parameters = new Array(); diff --git a/projects/subgraph-beanstalk/tests/event-mocking/SeedGauge.ts b/projects/subgraph-beanstalk/tests/event-mocking/SeedGauge.ts new file mode 100644 index 0000000000..6f3a95eeeb --- /dev/null +++ b/projects/subgraph-beanstalk/tests/event-mocking/SeedGauge.ts @@ -0,0 +1,124 @@ +import { Address, BigInt, Bytes, ethereum } from "@graphprotocol/graph-ts"; +import { newMockEvent } from "matchstick-as/assembly/index"; +import { + BeanToMaxLpGpPerBdvRatioChange, + GaugePointChange, + UpdateAverageStalkPerBdvPerSeason, + FarmerGerminatingStalkBalanceChanged, + TotalGerminatingBalanceChanged, + UpdateGaugeSettings +} from "../../generated/BIP42-SeedGauge/Beanstalk"; + +import { AddDeposit, RemoveDeposit, RemoveDeposits } from "../../generated/Silo-Replanted/Beanstalk"; +import { handleAddDeposit } from "../../src/SiloHandler"; +import { BEAN_DECIMALS } from "../../../subgraph-core/utils/Constants"; +import { BEANSTALK } from "../../../subgraph-core/utils/Constants"; + +// Default mock to include beanstalk address +const mockBeanstalkEvent = (): ethereum.Event => { + let e = changetype(newMockEvent()); + e.address = BEANSTALK; + return e; +}; + +export function createBeanToMaxLpGpPerBdvRatioChangeEvent( + season: BigInt, + caseId: BigInt, + absChange: BigInt +): BeanToMaxLpGpPerBdvRatioChange { + let event = changetype(mockBeanstalkEvent()); + event.parameters = new Array(); + + let param1 = new ethereum.EventParam("season", ethereum.Value.fromUnsignedBigInt(season)); + let param2 = new ethereum.EventParam("caseId", ethereum.Value.fromUnsignedBigInt(caseId)); + let param3 = new ethereum.EventParam("absChange", ethereum.Value.fromUnsignedBigInt(absChange)); + + event.parameters.push(param1); + event.parameters.push(param2); + event.parameters.push(param3); + + return event as BeanToMaxLpGpPerBdvRatioChange; +} + +export function createGaugePointChangeEvent(season: BigInt, token: string, gaugePoints: BigInt): GaugePointChange { + let event = changetype(mockBeanstalkEvent()); + event.parameters = new Array(); + + let param1 = new ethereum.EventParam("season", ethereum.Value.fromUnsignedBigInt(season)); + let param2 = new ethereum.EventParam("token", ethereum.Value.fromAddress(Address.fromString(token))); + let param3 = new ethereum.EventParam("gaugePoints", ethereum.Value.fromUnsignedBigInt(gaugePoints)); + + event.parameters.push(param1); + event.parameters.push(param2); + event.parameters.push(param3); + + return event as GaugePointChange; +} + +export function createUpdateAverageStalkPerBdvPerSeasonEvent(newStalkPerBdvPerSeason: BigInt): UpdateAverageStalkPerBdvPerSeason { + let event = changetype(mockBeanstalkEvent()); + event.parameters = new Array(); + + let param1 = new ethereum.EventParam("newStalkPerBdvPerSeason", ethereum.Value.fromUnsignedBigInt(newStalkPerBdvPerSeason)); + + event.parameters.push(param1); + + return event as UpdateAverageStalkPerBdvPerSeason; +} + +export function createFarmerGerminatingStalkBalanceChangedEvent(account: string, delta: BigInt): FarmerGerminatingStalkBalanceChanged { + let event = changetype(mockBeanstalkEvent()); + event.parameters = new Array(); + + let param1 = new ethereum.EventParam("account", ethereum.Value.fromAddress(Address.fromString(account))); + let param2 = new ethereum.EventParam("delta", ethereum.Value.fromUnsignedBigInt(delta)); + + event.parameters.push(param1); + event.parameters.push(param2); + + return event as FarmerGerminatingStalkBalanceChanged; +} + +export function createTotalGerminatingBalanceChangedEvent( + season: BigInt, + token: string, + delta: BigInt, + deltaBdv: BigInt +): TotalGerminatingBalanceChanged { + let event = changetype(mockBeanstalkEvent()); + event.parameters = new Array(); + + let param1 = new ethereum.EventParam("season", ethereum.Value.fromUnsignedBigInt(season)); + let param2 = new ethereum.EventParam("token", ethereum.Value.fromAddress(Address.fromString(token))); + let param3 = new ethereum.EventParam("delta", ethereum.Value.fromUnsignedBigInt(delta)); + let param4 = new ethereum.EventParam("deltaBdv", ethereum.Value.fromUnsignedBigInt(deltaBdv)); + + event.parameters.push(param1); + event.parameters.push(param2); + event.parameters.push(param3); + event.parameters.push(param4); + + return event as TotalGerminatingBalanceChanged; +} + +export function createUpdateGaugeSettingsEvent( + token: string, + gpSelector: string, + lwSelector: string, + optimalPercentDepositedBdv: BigInt +): UpdateGaugeSettings { + let event = changetype(mockBeanstalkEvent()); + event.parameters = new Array(); + + let param1 = new ethereum.EventParam("token", ethereum.Value.fromAddress(Address.fromString(token))); + let param2 = new ethereum.EventParam("gpSelector", ethereum.Value.fromBytes(Bytes.fromHexString(gpSelector))); + let param3 = new ethereum.EventParam("lwSelector", ethereum.Value.fromBytes(Bytes.fromHexString(lwSelector))); + let param4 = new ethereum.EventParam("optimalPercentDepositedBdv", ethereum.Value.fromUnsignedBigInt(optimalPercentDepositedBdv)); + + event.parameters.push(param1); + event.parameters.push(param2); + event.parameters.push(param3); + event.parameters.push(param4); + + return event as UpdateGaugeSettings; +} diff --git a/projects/subgraph-beanstalk/tests/event-mocking/Whitelist.ts b/projects/subgraph-beanstalk/tests/event-mocking/Whitelist.ts new file mode 100644 index 0000000000..82b4dfb239 --- /dev/null +++ b/projects/subgraph-beanstalk/tests/event-mocking/Whitelist.ts @@ -0,0 +1,46 @@ +import { Address, BigInt, Bytes, ethereum } from "@graphprotocol/graph-ts"; +import { newMockEvent } from "matchstick-as/assembly/index"; +import { WhitelistToken } from "../../generated/BIP42-SeedGauge/Beanstalk"; + +import { BEANSTALK } from "../../../subgraph-core/utils/Constants"; + +// Default mock to include beanstalk address +const mockBeanstalkEvent = (): ethereum.Event => { + let e = changetype(newMockEvent()); + e.address = BEANSTALK; + return e; +}; + +export function createWhitelistTokenEventBIP42( + token: string, + selector: string, + stalkEarnedPerSeason: BigInt, + stalkIssuedPerBdv: BigInt, + gpSelector: string, + lwSelector: string, + gaugePoints: BigInt, + optimalPercentDepositedBdv: BigInt +): WhitelistToken { + let event = changetype(mockBeanstalkEvent()); + event.parameters = new Array(); + + let param1 = new ethereum.EventParam("token", ethereum.Value.fromAddress(Address.fromString(token))); + let param2 = new ethereum.EventParam("selector", ethereum.Value.fromBytes(Bytes.fromHexString(selector))); + let param3 = new ethereum.EventParam("stalkEarnedPerSeason", ethereum.Value.fromUnsignedBigInt(stalkEarnedPerSeason)); + let param4 = new ethereum.EventParam("stalkIssuedPerBdv", ethereum.Value.fromUnsignedBigInt(stalkIssuedPerBdv)); + let param5 = new ethereum.EventParam("gpSelector", ethereum.Value.fromBytes(Bytes.fromHexString(gpSelector))); + let param6 = new ethereum.EventParam("lwSelector", ethereum.Value.fromBytes(Bytes.fromHexString(lwSelector))); + let param7 = new ethereum.EventParam("gaugePoints", ethereum.Value.fromUnsignedBigInt(gaugePoints)); + let param8 = new ethereum.EventParam("optimalPercentDepositedBdv", ethereum.Value.fromUnsignedBigInt(optimalPercentDepositedBdv)); + + event.parameters.push(param1); + event.parameters.push(param2); + event.parameters.push(param3); + event.parameters.push(param4); + event.parameters.push(param5); + event.parameters.push(param6); + event.parameters.push(param7); + event.parameters.push(param8); + + return event as WhitelistToken; +} diff --git a/projects/subgraph-core/tests/event-mocking/Prices.ts b/projects/subgraph-core/tests/event-mocking/Prices.ts new file mode 100644 index 0000000000..053a478ccc --- /dev/null +++ b/projects/subgraph-core/tests/event-mocking/Prices.ts @@ -0,0 +1,127 @@ +import { BigInt, ethereum, Address } from "@graphprotocol/graph-ts"; +import { createMockedFunction } from "matchstick-as/assembly/index"; +import { BEAN_3CRV, BEAN_ERC20, BEAN_WETH_CP2_WELL, BEANSTALK_PRICE, CURVE_PRICE, WETH } from "../../utils/Constants"; + +// These 2 classes are analagous to structs used by BeanstalkPrice contract +class Prices { + price: BigInt; + liquidity: BigInt; + deltaB: BigInt; + ps: Pool[]; +} + +class Pool { + contract: Address; + tokens: Address[]; + balances: BigInt[]; + price: BigInt; + liquidity: BigInt; + deltaB: BigInt; + lpUsd: BigInt; + lpBdv: BigInt; +} + +/** + * Mocks the return values from BeanstalkPrice contract + * @param prices - the Prices struct that the contract will return + * @param mockPools - when true, mocks the return values from the individual pools' price call also + */ +export function setMockBeanPrice(prices: Prices, mockPools: boolean = true): void { + const pricesReturn = toPricesStruct(prices); + + createMockedFunction( + BEANSTALK_PRICE, + "price", + "price():((uint256,uint256,int256,(address,address[2],uint256[2],uint256,uint256,int256,uint256,uint256)[]))" + ) + // @ts-expect-error:2322 + .returns([ethereum.Value.fromTuple(pricesReturn)]); + + if (mockPools) { + for (let i = 0; i < prices.ps.length; ++i) { + if (prices.ps[i].contract == BEAN_3CRV) { + setMockCurvePrice(prices.ps[i]); + } else { + setMockWellPrice(prices.ps[i]); + } + } + } +} + +export function setMockCurvePrice(pool: Pool): void { + const curvePriceReturn = toPoolStruct(pool); + + createMockedFunction(CURVE_PRICE, "getCurve", "getCurve():((address,address[2],uint256[2],uint256,uint256,int256,uint256,uint256))") + .withArgs([]) + .returns([ethereum.Value.fromTuple(curvePriceReturn)]); +} + +export function setMockWellPrice(pool: Pool): void { + const wellPriceReturn = toPoolStruct(pool); + + createMockedFunction( + BEANSTALK_PRICE, + "getConstantProductWell", + "getConstantProductWell(address):((address,address[2],uint256[2],uint256,uint256,int256,uint256,uint256))" + ) + .withArgs([ethereum.Value.fromAddress(pool.contract)]) + .returns([ethereum.Value.fromTuple(wellPriceReturn)]); +} + +const price = (p: number): BigInt => BigInt.fromU32((p * Math.pow(10, 6))); + +export const simpleMockPrice = (overall: number, beanEth: number): void => { + setMockBeanPrice({ + price: price(overall), + liquidity: BigInt.zero(), + deltaB: BigInt.zero(), + ps: [ + { + contract: BEAN_WETH_CP2_WELL, + tokens: [BEAN_ERC20, WETH], + balances: [BigInt.fromString("10"), BigInt.fromString("10")], + price: price(beanEth), + liquidity: BigInt.fromString("10"), + deltaB: BigInt.fromString("10"), + lpUsd: BigInt.fromString("10"), + lpBdv: BigInt.fromString("10") + } + ] + }); +}; + +function toPricesStruct(prices: Prices): ethereum.Tuple { + let retval = new ethereum.Tuple(); + + retval.push(ethereum.Value.fromUnsignedBigInt(prices.price)); + retval.push(ethereum.Value.fromUnsignedBigInt(prices.liquidity)); + retval.push(ethereum.Value.fromSignedBigInt(prices.deltaB)); + + const pools: ethereum.Tuple[] = []; + for (let i = 0; i < prices.ps.length; ++i) { + pools.push(toPoolStruct(prices.ps[i])); + } + retval.push(ethereum.Value.fromTupleArray(pools)); + + return retval; +} + +function toPoolStruct(pool: Pool): ethereum.Tuple { + const ethereumTokens: ethereum.Value[] = []; + for (let i = 0; i < pool.tokens.length; ++i) { + ethereumTokens.push(ethereum.Value.fromAddress(pool.tokens[i])); + } + + let retval = new ethereum.Tuple(); + + retval.push(ethereum.Value.fromAddress(pool.contract)); + retval.push(ethereum.Value.fromArray(ethereumTokens)); + retval.push(ethereum.Value.fromUnsignedBigIntArray(pool.balances)); + retval.push(ethereum.Value.fromUnsignedBigInt(pool.price)); + retval.push(ethereum.Value.fromUnsignedBigInt(pool.liquidity)); + retval.push(ethereum.Value.fromSignedBigInt(pool.deltaB)); + retval.push(ethereum.Value.fromUnsignedBigInt(pool.lpUsd)); + retval.push(ethereum.Value.fromUnsignedBigInt(pool.lpBdv)); + + return retval; +}