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

fix: extend trading limits functions to multiple assets #58

Merged
merged 4 commits into from
Jun 7, 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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@mento-protocol/mento-sdk",
"description": "Official SDK for interacting with the Mento Protocol",
"version": "0.2.8",
"version": "1.0.0",
"license": "MIT",
"author": "Mento Labs",
"keywords": [
Expand Down
5 changes: 4 additions & 1 deletion src/interfaces/tradingLimitsConfig.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { Address } from './tradingLimit'

export interface TradingLimitsConfig {
asset: Address
timestep0: number
timestep1: number
limit0: number
limit1: number
limitGlobal: number
flags: number
}
}
3 changes: 3 additions & 0 deletions src/interfaces/tradingLimitsState.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { Address } from './tradingLimit'

export interface TradingLimitsState {
asset: Address
lastUpdated0: number
lastUpdated1: number
netflow0: number
Expand Down
54 changes: 51 additions & 3 deletions src/limits.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ jest.mock('@mento-protocol/mento-core-ts', () => {
})

// ========== Mock data ==========
const fakeAsset = '0x62492A644A588FD904270BeD06ad52B9abfEA1aE'
const fakeExchangeId =
'0x3135b662c38265d0655177091f1b647b4fef511103d06c016efdf18b46930d2c'

const fakeLimitConfig = {
asset: fakeAsset,
timestep0: 300,
timestep1: 86400,
limit0: 100000,
Expand All @@ -26,15 +31,13 @@ const fakeLimitConfig = {
flags: 3,
}
const fakeLimitState = {
asset: fakeAsset,
lastUpdated0: 1681381868,
lastUpdated1: 1681375758,
netflow0: 15,
netflow1: 20,
netflowGlobal: 0,
}
const fakeExchangeId =
'0x3135b662c38265d0655177091f1b647b4fef511103d06c016efdf18b46930d2c'
const fakeAsset = '0x62492A644A588FD904270BeD06ad52B9abfEA1aE'

// ========== Mock contract factories ==========
const mockBrokerFactory = {
Expand Down Expand Up @@ -222,6 +225,51 @@ describe('Limits', () => {
const limits = await getLimits(broker, fakeExchangeId, fakeAsset)
expect(limits.length).toEqual(3)
})

it('should constrain smaller limits according to bigger ones', async () => {
const nowEpoch = Math.floor(Date.now() / 1000)
const cfg = {
...fakeLimitConfig,
limit0: 100,
limit1: 1000,
limitGlobal: 10000,
}
const stateWithL1ConstrainingL0 = {
...fakeLimitState,
lastUpdated0: nowEpoch,
lastUpdated1: nowEpoch,
netflow0: 25,
netflow1: 995,
netflowGlobal: 1020,
}

mockBrokerFactory.tradingLimitsConfig.mockResolvedValue(cfg)
mockBrokerFactory.tradingLimitsState.mockResolvedValue(
stateWithL1ConstrainingL0
)

const broker = Broker__factory.connect('0xfakeBrokerAddr', provider)
const limits = await getLimits(broker, fakeExchangeId, fakeAsset)
expect(limits.length).toEqual(3)
expect(limits[0].maxIn).toEqual(5)
expect(limits[1].maxIn).toEqual(5)
expect(limits[2].maxIn).toEqual(8980)

const stateWithLGMaxedOut = {
...fakeLimitState,
lastUpdated0: nowEpoch,
lastUpdated1: nowEpoch,
netflow0: 25,
netflow1: 25,
netflowGlobal: cfg.limitGlobal,
}
mockBrokerFactory.tradingLimitsState.mockResolvedValue(
stateWithLGMaxedOut
)
const maxedOutLimits = await getLimits(broker, fakeExchangeId, fakeAsset)
expect(maxedOutLimits.length).toEqual(3)
expect(maxedOutLimits.every((limit) => limit.maxIn === 0)).toBe(true)
})
})

describe('getLimitId', () => {
Expand Down
9 changes: 9 additions & 0 deletions src/limits.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export async function getLimitsConfig(
const cfg = await broker.tradingLimitsConfig(limitId)

return {
asset,
timestep0: cfg['timestep0'],
timestep1: cfg['timestep1'],
limit0: cfg['limit0'],
Expand Down Expand Up @@ -63,6 +64,7 @@ export async function getLimitsState(
isL1Enabled && nowEpoch > state['lastUpdated1'] + cfg.timestep1

return {
asset,
lastUpdated0: isL0Outdated ? nowEpoch : state['lastUpdated0'],
lastUpdated1: isL1Outdated ? nowEpoch : state['lastUpdated1'],
netflow0: isL0Outdated ? 0 : state['netflow0'],
Expand Down Expand Up @@ -117,6 +119,13 @@ export async function getLimits(
})
}

// Limits with a smaller timeframe are restricted by the ones with a larger one
// e.g: if maxIn is 0 in LG, it should also be 0 in L1 and L0
for (let i = limits.length - 1; i > 0; i--) {
limits[i - 1].maxIn = Math.min(limits[i - 1].maxIn, limits[i].maxIn)
limits[i - 1].maxOut = Math.min(limits[i - 1].maxOut, limits[i].maxOut)
}

return limits
}

Expand Down
36 changes: 26 additions & 10 deletions src/mento.ts
Original file line number Diff line number Diff line change
Expand Up @@ -403,41 +403,57 @@ export class Mento {
this.signerOrProvider
)

const assetWithLimit = exchange.assets[0] // currently limits are configured only on asset0
return getLimits(broker, exchangeId, assetWithLimit)
const asset0Limits = await getLimits(broker, exchangeId, exchange.assets[0])
const asset1Limits = await getLimits(broker, exchangeId, exchange.assets[1])

return asset0Limits.concat(asset1Limits)
}

/**
* Returns the trading limits configuration for a given exchange id
* Returns the trading limits configurations for a given exchange id
* @param exchangeId the id of the exchange
* @returns the trading limits configuration
*/
async getTradingLimitConfig(
exchangeId: string
): Promise<TradingLimitsConfig> {
): Promise<TradingLimitsConfig[]> {
const exchange = await this.getExchangeById(exchangeId)
const broker = Broker__factory.connect(
this.broker.address,
this.signerOrProvider
)

const assetWithLimit = exchange.assets[0] // currently limits are configured only on asset0
return getLimitsConfig(broker, exchangeId, assetWithLimit)
const cfgs = []
for (const asset of exchange.assets) {
const limitCfg = await getLimitsConfig(broker, exchangeId, asset)
const isLimitConfigured = limitCfg.flags > 0
if (isLimitConfigured) {
cfgs.push(limitCfg)
}
}

return cfgs
}

/**
* Returns the trading limits state for a given exchange id
* @param exchangeId the id of the exchange
* @returns the trading limits state
*/
async getTradingLimitState(exchangeId: string): Promise<TradingLimitsState> {
const exchange = await this.getExchangeById(exchangeId)
async getTradingLimitState(
exchangeId: string
): Promise<TradingLimitsState[]> {
const broker = Broker__factory.connect(
this.broker.address,
this.signerOrProvider
)

const assetWithLimit = exchange.assets[0] // currently limits are configured only on asset0
return getLimitsState(broker, exchangeId, assetWithLimit)
const configuredLimitCfgs = await this.getTradingLimitConfig(exchangeId)

return await Promise.all(
configuredLimitCfgs.map(
async (cfg) => await getLimitsState(broker, exchangeId, cfg.asset)
)
)
}
}
Loading