Skip to content

Commit

Permalink
Feat/tests (#44)
Browse files Browse the repository at this point in the history
* feat: add tests

* chore: format

* feat: tests

* chore: lint

* feat: token list export

* Version Packages

* chore: format

* feat: getKandelSteps without kandel address

* Version Packages

* chore: format

* feat: SmartKandel address for blast

* chore: version package

* chore: format

* feat: add tests

* chore: format

* feat: tests

* chore: lint

* test: Update distribution test in kandel library.

* feat: Add deployment of SmartKandel Seeder contract in global setup.

* chore: format

* test: Ensure distribution and logs tests are passing.

* chore: format

* chore: Add default gasreq to kandel.

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: maxencerb <[email protected]>
  • Loading branch information
3 people authored May 22, 2024
1 parent 41490ef commit 185dadb
Show file tree
Hide file tree
Showing 18 changed files with 457 additions and 40 deletions.
5 changes: 5 additions & 0 deletions .changeset/four-mirrors-sort.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@mangrovedao/mgv": patch
---

Add default gasreq to kandel
1 change: 0 additions & 1 deletion contracts/.gitignore

This file was deleted.

10 changes: 2 additions & 8 deletions src/actions/book.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { http, createPublicClient } from 'viem'
import { blast } from 'viem/chains'
import { describe, expect, inject, it } from 'vitest'
import { getClient } from '~test/src/client.js'
import { getBook } from './book.js'

const { WETH, DAI } = inject('tokens')
const { wethDAI } = inject('markets')
const { mangrove, reader, order } = inject('mangrove')

describe('Getting the book', () => {
Expand All @@ -17,11 +15,7 @@ describe('Getting the book', () => {
mgvReader: reader,
mgvOrder: order,
},
{
base: { address: WETH, decimals: 18 },
quote: { address: DAI, decimals: 18 },
tickSpacing: 1n,
},
wethDAI,
)
expect(book.marketConfig).toEqual({
monitor: '0x0000000000000000000000000000000000000000',
Expand Down
16 changes: 14 additions & 2 deletions src/actions/kandel/steps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { getLogicsParams } from '../../builder/kandel/logic.js'
// import { getParamsParams } from '../../builder/kandel/populate.js'
import { tokenAllowanceParams } from '../../builder/tokens.js'
import type { KandelSteps, MarketParams } from '../../index.js'
import { getKandelGasReq } from '../../lib/kandel/params.js'
import { getAction } from '../../utils/getAction.js'
import type { OverlyingResult } from '../balances.js'

Expand All @@ -33,7 +34,6 @@ export type GetKandelStepsParams = {
user: Address
baseOverlying?: OverlyingResult
quoteOverlying?: OverlyingResult
gasreq: bigint
}

export type GetKandelStepsArgs = GetKandelStepsParams &
Expand Down Expand Up @@ -96,6 +96,11 @@ export async function getKandelSteps(
allowFailure: true,
})

const gasreq = getKandelGasReq({
baseLogic: args.baseOverlying?.logic,
quoteLogic: args.quoteOverlying?.logic,
})

return [
{
type: 'sowKandel',
Expand Down Expand Up @@ -128,7 +133,7 @@ export async function getKandelSteps(
kandel,
baseLogic: args.baseOverlying?.logic,
quoteLogic: args.quoteOverlying?.logic,
gasRequirement: args.gasreq,
gasRequirement: gasreq,
},
done:
(logics.status === 'success' &&
Expand Down Expand Up @@ -179,5 +184,12 @@ export async function getKandelSteps(
quoteAllowance.status === 'success' &&
quoteAllowance.result > maxUint128,
},
{
type: 'populate',
params: {
gasreq,
},
done: false,
},
]
}
4 changes: 2 additions & 2 deletions src/actions/market-order.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ const client = getClient()

describe('market-order', () => {
it('should deal balance', async () => {
await mint(client, WETH, client.account.address, 100n)
await mint(client, WETH.address, client.account.address, 100n)
const balance = await client.readContract({
address: WETH,
address: WETH.address,
abi: erc20Abi,
functionName: 'balanceOf',
args: [client.account.address],
Expand Down
106 changes: 106 additions & 0 deletions src/lib/human-readable.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { parseUnits } from 'viem'
import { describe, expect, inject, it } from 'vitest'
import { BA } from './enums.js'
import {
amounts,
amountsToHumanPrice,
humanPriceToRawPrice,
rawPriceToHumanPrice,
rpcOfferToHumanOffer,
} from './human-readable.js'
import { tickFromVolumes } from './tick.js'

const { wethUSDC } = inject('markets')
const { USDC, WETH } = inject('tokens')

// price is quote/base
// USDC is 6 decimals
// DAI and WETH are 18 decimals

describe('human readable', () => {
it('rawPriceToHumanPrice', () => {
const humanPrice = 3000
const rawPrice = (3000 * 1e6) / 1e18
const price = rawPriceToHumanPrice(rawPrice, wethUSDC)
expect(price).toBe(humanPrice)
})

it('humanPriceToRawPrice', () => {
const humanPrice = 3000
const rawPrice = (3000 * 1e6) / 1e18
const price = humanPriceToRawPrice(humanPrice, wethUSDC)
expect(price).toBe(rawPrice)
})

it('amountsToHumanPrice', () => {
const amountUSDC = parseUnits('3000', USDC.decimals)
const amountWETH = parseUnits('1', WETH.decimals)
const price = amountsToHumanPrice(
{ baseAmount: amountWETH, quoteAmount: amountUSDC },
wethUSDC,
)
expect(price).toBe(3000)
})

it('amounts', () => {
const humanPrice = 3000
const baseAmount = parseUnits('1', WETH.decimals)
const quoteAmount = parseUnits('3000', USDC.decimals)

expect(
amounts({ baseAmount, quoteAmount }, wethUSDC),
'Wrong human price',
).toEqual(expect.objectContaining({ baseAmount, quoteAmount, humanPrice }))

expect(
amounts({ humanPrice, baseAmount }, wethUSDC).quoteAmount,
'Wrong quote amount',
).toApproximateEqual(quoteAmount, 0.0001)

expect(
amounts({ humanPrice, quoteAmount }, wethUSDC).baseAmount,
'Wrong base amount',
).toApproximateEqual(baseAmount, 0.0001)
})

it('rpcOfferToHumanOffer', () => {
const baseAmount = parseUnits('1', WETH.decimals)
const quoteAmount = parseUnits('3000', USDC.decimals)
const tickBid = tickFromVolumes(
baseAmount,
quoteAmount,
wethUSDC.tickSpacing,
)
const tickAsk = tickFromVolumes(
quoteAmount,
baseAmount,
wethUSDC.tickSpacing,
)
const humanPrice = 3000
const offerBid = rpcOfferToHumanOffer({
gives: quoteAmount,
tick: tickBid,
ba: BA.bids,
baseDecimals: WETH.decimals,
quoteDecimals: USDC.decimals,
})

expect(offerBid.price).toApproximateEqual(humanPrice, 0.0001)
expect(offerBid.total).toApproximateEqual(3000, 0.0001)
expect(offerBid.volume).toApproximateEqual(1, 0.0001)
expect(offerBid.ba).toBe(BA.bids)

const offerAsk = rpcOfferToHumanOffer({
gives: baseAmount,
tick: tickAsk,
ba: BA.asks,
baseDecimals: WETH.decimals,
quoteDecimals: USDC.decimals,
})

expect(offerAsk.price).toApproximateEqual(humanPrice, 0.0001)
expect(offerAsk.total).toApproximateEqual(3000, 0.0001)
expect(offerAsk.volume).toApproximateEqual(1, 0.0001)
expect(offerAsk.ba).toBe(BA.asks)
})
})
90 changes: 90 additions & 0 deletions src/lib/kandel/distribution.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { parseAbi } from 'viem'
import { expect, it } from 'vitest'
import { describe, inject } from 'vitest'
import { getClient } from '~test/src/client.js'
import { createGeometricDistribution } from './distribution.js'
import { getKandelPositionRawParams } from './params.js'

const { kandelLib, smartKandelSeeder } = inject('kandel')
const { routerProxyFactory, mangrove } = inject('mangrove')
const { wethUSDC } = inject('markets')

const client = getClient()

const kandelLibAbi = parseAbi([
'struct DistributionOffer {uint index;int tick;uint gives;}',
'struct Distribution {DistributionOffer[] asks;DistributionOffer[] bids;}',
'function createGeometricDistribution(uint from,uint to,int baseQuoteTickIndex0,uint _baseQuoteTickOffset,uint firstAskIndex,uint bidGives,uint askGives,uint pricePoints,uint stepSize) external pure returns (Distribution memory distribution)',
])

describe('distribution', () => {
it('checks kandel deployment', async () => {
const [factory, mgv] = await client.multicall({
contracts: [
{
address: smartKandelSeeder,
abi: parseAbi(['function PROXY_FACTORY() view returns (address)']),
functionName: 'PROXY_FACTORY',
},
{
address: smartKandelSeeder,
abi: parseAbi(['function MGV() view returns (address)']),
functionName: 'MGV',
},
],
})
expect(factory.status).toEqual('success')
expect(factory.result).toAddressEqual(routerProxyFactory)
expect(mgv.status).toEqual('success')
expect(mgv.result).toAddressEqual(mangrove)
})

it('checks kandel distribution', async () => {
const params = getKandelPositionRawParams({
minPrice: 2500,
midPrice: 3000,
maxPrice: 3500,
pricePoints: 10n,
market: wethUSDC,
})

const distrib = createGeometricDistribution({
...params,
stepSize: 1n,
market: wethUSDC,
bidGives: 1n,
askGives: 1n,
})

const fromChain = await client.readContract({
address: kandelLib,
abi: kandelLibAbi,
functionName: 'createGeometricDistribution',
args: [
0n,
10n,
params.baseQuoteTickIndex0,
params.baseQuoteTickOffset,
params.firstAskIndex,
1n,
1n,
params.pricePoints,
1n,
],
})

expect(distrib.asks.length).toEqual(fromChain.asks.length)
expect(distrib.bids.length).toEqual(fromChain.bids.length)

for (let i = 0; i < distrib.asks.length; i++) {
expect(distrib.asks[i].gives).toEqual(fromChain.asks[i].gives)
expect(distrib.asks[i].tick).toEqual(fromChain.asks[i].tick)
expect(distrib.asks[i].index).toEqual(fromChain.asks[i].index)
}
for (let i = 0; i < distrib.bids.length; i++) {
expect(distrib.bids[i].gives).toEqual(fromChain.bids[i].gives)
expect(distrib.bids[i].tick).toEqual(fromChain.bids[i].tick)
expect(distrib.bids[i].index).toEqual(fromChain.bids[i].index)
}
})
})
32 changes: 32 additions & 0 deletions src/lib/kandel/logs.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { isAddress } from 'viem'
import { describe, expect, inject, it } from 'vitest'
import { simulateSow } from '~mgv/actions/kandel/sow.js'
import { getClient } from '~test/src/client.js'
import { hash } from '../ol-key.js'
import { getKandelsFromLogs } from './logs.js'

const { smartKandelSeeder } = inject('kandel')
const { wethUSDC } = inject('markets')
const client = getClient()

describe('Kandel logs', () => {
it('get smart kandel from logs', async () => {
const { request } = await simulateSow(client, wethUSDC, smartKandelSeeder)
const tx = await client.writeContract(request)
const receipt = await client.waitForTransactionReceipt({
hash: tx,
})
const result = getKandelsFromLogs(receipt.logs)
expect(result.length).toEqual(1)
expect(result[0].type).toEqual('SmartKandel')
expect(result[0].owner).toAddressEqual(client.account.address)
expect(result[0].baseQuoteOlKeyHash).toEqual(
hash({
outbound_tkn: wethUSDC.base.address,
inbound_tkn: wethUSDC.quote.address,
tickSpacing: wethUSDC.tickSpacing,
}),
)
expect(isAddress(result[0].address))
})
})
37 changes: 37 additions & 0 deletions src/lib/kandel/params.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { describe, expect, inject, it } from 'vitest'
import {
humanPriceToRawPrice,
rawPriceToHumanPrice,
} from '../human-readable.js'
import { priceFromTick, tickFromPrice } from '../tick.js'
import { getKandelPositionRawParams } from './params.js'

const { wethUSDC } = inject('markets')

describe('kandel params', () => {
it('kandel position raw params', () => {
const params = getKandelPositionRawParams({
minPrice: 2500,
midPrice: 3000,
maxPrice: 3500,
pricePoints: 10n,
market: wethUSDC,
})

expect(params.pricePoints).toBe(10n)
expect(params.firstAskIndex).toBe(5n)

const baseQuoteTickIndex0 = tickFromPrice(
humanPriceToRawPrice(2500, wethUSDC),
wethUSDC.tickSpacing,
)
expect(params.baseQuoteTickIndex0).toBe(baseQuoteTickIndex0)
expect(params.baseQuoteTickOffset % wethUSDC.tickSpacing).toBe(0n)

const endTick =
params.baseQuoteTickIndex0 +
params.baseQuoteTickOffset * (params.pricePoints - 1n)
const endPrice = rawPriceToHumanPrice(priceFromTick(endTick), wethUSDC)
expect(endPrice).toApproximateEqual(3500)
})
})
Loading

0 comments on commit 185dadb

Please sign in to comment.