Skip to content

Commit

Permalink
feat: update kandel (#66)
Browse files Browse the repository at this point in the history
  • Loading branch information
maxencerb authored May 27, 2024
1 parent d58a776 commit 8738527
Show file tree
Hide file tree
Showing 8 changed files with 201 additions and 91 deletions.
5 changes: 5 additions & 0 deletions .changeset/fast-parents-accept.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@mangrovedao/mgv": minor
---

Changes kandel client to receive action params
5 changes: 5 additions & 0 deletions .changeset/rotten-meals-bake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@mangrovedao/mgv": patch
---

Added provisions and offer id to kandel view
5 changes: 5 additions & 0 deletions .changeset/weak-dolphins-boil.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@mangrovedao/mgv": minor
---

Changes getSemiBookOlKeys to get market params
8 changes: 2 additions & 6 deletions src/actions/book.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,9 @@ export async function getBook(
): Promise<Book> {
const { depth = 100n, ...multicallParams } = parameters || {}
const { mgv, mgvReader } = actionParams
const { base, quote, tickSpacing } = marketParams
const { base, quote } = marketParams

const { asksMarket, bidsMarket } = getSemibooksOLKeys({
base: base.address,
quote: quote.address,
tickSpacing,
})
const { asksMarket, bidsMarket } = getSemibooksOLKeys(marketParams)

const [rpcAsks, rpcBids, rpcAsksConfig, rpcBaseConfig, rpcMarketConfig] =
await getAction(
Expand Down
201 changes: 142 additions & 59 deletions src/actions/kandel/view.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
import type { Address, Client, MulticallParameters } from 'viem'
import {
type Address,
type Client,
type MulticallParameters,
erc20Abi,
} from 'viem'
import { multicall } from 'viem/actions'
import {
baseQuoteTickOffsetParams,
getOfferParams,
kandelParamsParams,
offerIdOfIndexParams,
offeredVolumeParams,
provisionOfParams,
} from '../../builder/kandel/view.js'
import { type MarketParams, priceFromTick } from '../../index.js'
import {
type MangroveActionsDefaultParams,
type MarketParams,
priceFromTick,
} from '../../index.js'
import { BA } from '../../lib/enums.js'
import { rawPriceToHumanPrice } from '../../lib/human-readable.js'
import { unpackOffer } from '../../lib/offer.js'
import { getSemibooksOLKeys } from '../../lib/ol-key.js'
import { getAction } from '../../utils/getAction.js'

export type GetKandelStateParams = {}
Expand All @@ -18,11 +30,13 @@ export type GetKandelStateArgs = GetKandelStateParams &
Omit<MulticallParameters, 'contracts' | 'allowFailure'>

type OfferParsed = {
id: bigint
tick: bigint
gives: bigint
price: number
ba: BA
index: bigint
provision: bigint
}

export type GetKandelStateResult = {
Expand All @@ -33,43 +47,56 @@ export type GetKandelStateResult = {
pricePoints: number
quoteAmount: bigint
baseAmount: bigint
unlockedProvision: bigint
asks: OfferParsed[]
bids: OfferParsed[]
}

export async function getKandelState(
client: Client,
actionsParams: MangroveActionsDefaultParams,
market: MarketParams,
kandel: Address,
args: GetKandelStateArgs,
): Promise<GetKandelStateResult> {
const [baseQuoteTickOffset, params, quoteAmount, baseAmount] =
await getAction(
client,
multicall,
'multicall',
)({
...args,
contracts: [
{
address: kandel,
...baseQuoteTickOffsetParams,
},
{
address: kandel,
...kandelParamsParams,
},
{
address: kandel,
...offeredVolumeParams(BA.bids),
},
{
address: kandel,
...offeredVolumeParams(BA.asks),
},
],
allowFailure: true,
})
const [
baseQuoteTickOffset,
params,
quoteAmount,
baseAmount,
unlockedProvision,
] = await getAction(
client,
multicall,
'multicall',
)({
...args,
contracts: [
{
address: kandel,
...baseQuoteTickOffsetParams,
},
{
address: kandel,
...kandelParamsParams,
},
{
address: kandel,
...offeredVolumeParams(BA.bids),
},
{
address: kandel,
...offeredVolumeParams(BA.asks),
},
{
address: actionsParams.mgv,
abi: erc20Abi,
functionName: 'balanceOf',
args: [kandel],
},
],
allowFailure: true,
})

const pricePoints =
params.status === 'success' ? params.result.pricePoints : 0
Expand All @@ -93,39 +120,93 @@ export async function getKandelState(
address: kandel,
...getOfferParams(BA.asks, BigInt(i)),
},
{
address: kandel,
...offerIdOfIndexParams(BA.bids, BigInt(i)),
},
{
address: kandel,
...offerIdOfIndexParams(BA.asks, BigInt(i)),
},
]),
})

asks.push(
...offers
.filter((_, i) => i % 2 === 1)
.flatMap((offer, index) =>
offer.status === 'success'
? { ...unpackOffer(offer.result), index: BigInt(index) }
: [],
)
.filter((o) => o.gives > 0n)
.map((offer) => ({
...offer,
ba: BA.asks,
price: rawPriceToHumanPrice(priceFromTick(-offer.tick), market),
})),
)
bids.push(
...offers
.filter((_, i) => i % 2 === 0)
.flatMap((offer, index) =>
offer.status === 'success'
? { ...unpackOffer(offer.result), index: BigInt(index) }
: [],
)
.filter((o) => o.gives > 0n)
.map((offer) => ({
...offer,
ba: BA.bids,
price: rawPriceToHumanPrice(priceFromTick(offer.tick), market),
})),
)
if (offers.length !== pricePoints * 4) {
throw new Error('unexpected number of offers')
}

for (let index = 0; index < offers.length; index += 4) {
const [rawBid, rawAsk, rawBidId, rawAskId] = offers.slice(
index,
index + 4,
)
if (rawBid?.status === 'success' && rawBidId?.status === 'success') {
const bid = unpackOffer(rawBid.result)
const bidId = rawBidId.result
if (bidId > 0n) {
bids.push({
...bid,
index: BigInt(index / 4),
id: bidId,
price: rawPriceToHumanPrice(priceFromTick(-bid.tick), market),
ba: BA.bids,
provision: 0n,
})
}
}
if (rawAsk?.status === 'success' && rawAskId?.status === 'success') {
const ask = unpackOffer(rawAsk.result)
const askId = rawAskId.result
if (askId > 0n) {
asks.push({
...ask,
index: BigInt(index / 4),
id: askId,
price: rawPriceToHumanPrice(priceFromTick(ask.tick), market),
ba: BA.asks,
provision: 0n,
})
}
}
}

if (bids.length || asks.length) {
const { asksMarket, bidsMarket } = getSemibooksOLKeys(market)
const provisions = await getAction(
client,
multicall,
'multicall',
)({
allowFailure: true,
...args,
contracts: [
...bids.map((bid) => ({
address: kandel,
...provisionOfParams(bidsMarket, bid.id),
})),
...asks.map((ask) => ({
address: kandel,
...provisionOfParams(asksMarket, ask.id),
})),
],
})
for (let i = 0; i < bids.length && i < provisions.length; i++) {
if (bids[i]!.gives === 0n) continue
const value = provisions[i]
const provision = value?.status === 'success' ? value.result : 0n
bids[i]!.provision = provision
}
for (
let i = 0;
i < asks.length && i + bids.length < provisions.length;
i++
) {
if (asks[i]!.gives === 0n) continue
const value = provisions[i + bids.length]
const provision = value?.status === 'success' ? value.result : 0n
asks[i]!.provision = provision
}
}
}

return {
Expand All @@ -137,6 +218,8 @@ export async function getKandelState(
gasreq: params.status === 'success' ? params.result.gasreq : 0,
stepSize: params.status === 'success' ? params.result.stepSize : 0,
pricePoints,
unlockedProvision:
unlockedProvision.status === 'success' ? unlockedProvision.result : 0n,
quoteAmount: quoteAmount.status === 'success' ? quoteAmount.result : 0n,
baseAmount: baseAmount.status === 'success' ? baseAmount.result : 0n,
asks,
Expand Down
15 changes: 15 additions & 0 deletions src/builder/kandel/view.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
import { type ContractFunctionParameters, parseAbi } from 'viem'
import { BA } from '../../lib/enums.js'
import type { OLKey } from '../../types/lib.js'
import { olKeyABIRaw } from '../structs.js'

export const paramsStruct =
'struct Params { uint32 gasprice; uint24 gasreq; uint32 stepSize; uint32 pricePoints; }' as const

// ba: 0 is bid, 1 is ask
export const viewKandelABI = parseAbi([
paramsStruct,
olKeyABIRaw,
'function baseQuoteTickOffset() public view returns (uint)',
'function params() public view returns (Params memory)',
'function offeredVolume(uint8 ba) public view returns (uint volume)',
'function getOffer(uint8 ba, uint index) public view returns (uint offer)',
'function offerIdOfIndex(uint8 ba, uint index) public view returns (uint offerId)',
'function provisionOf(OLKey memory olKey, uint offerId) public view returns (uint provision)',
])

export const baseQuoteTickOffsetParams = {
Expand Down Expand Up @@ -70,3 +74,14 @@ export function offerIdOfIndexParams(ba: BA, index: bigint) {
'address'
>
}

export function provisionOfParams(olKey: OLKey, offerId: bigint) {
return {
abi: viewKandelABI,
functionName: 'provisionOf',
args: [olKey, offerId],
} satisfies Omit<
ContractFunctionParameters<typeof viewKandelABI, 'view', 'provisionOf'>,
'address'
>
}
32 changes: 18 additions & 14 deletions src/bundle/public/kandel-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ import {
type GetKandelStateResult,
getKandelState,
} from '../../actions/kandel/view.js'
import type { KandelSteps, MarketParams } from '../../index.js'
import type {
KandelSteps,
MangroveActionsDefaultParams,
MarketParams,
} from '../../index.js'

export type KandelSeederActions = {
getKandelSteps: (args: GetKandelStepsArgs) => Promise<KandelSteps>
Expand All @@ -55,22 +59,22 @@ export type KandelActions = {
args: PopulateChunkArgs,
) => Promise<PopulateChunkResult>
simulateRetract: (args: RetractArgs) => Promise<SimulateRetractResult>
getKandelState: (args: GetKandelStateArgs) => Promise<GetKandelStateResult>
getKandelState: (args?: GetKandelStateArgs) => Promise<GetKandelStateResult>
}

export function kandelActions(market: MarketParams, kandel: Address) {
export function kandelActions(
actionParams: MangroveActionsDefaultParams,
market: MarketParams,
kandel: Address,
) {
return (client: Client): KandelActions => ({
getKandelSteps: (args: GetKandelStepsArgs) =>
getKandelSteps(client, market, kandel, args),
simulateSetLogics: (args: SetLogicsArgs) =>
simulateSetLogics(client, kandel, args),
simulatePopulate: (args: PopulateArgs) =>
simulatePopulate(client, kandel, args),
simulatePopulateChunk: (args: PopulateChunkArgs) =>
getKandelSteps: (args) => getKandelSteps(client, market, kandel, args),
simulateSetLogics: (args) => simulateSetLogics(client, kandel, args),
simulatePopulate: (args) => simulatePopulate(client, kandel, args),
simulatePopulateChunk: (args) =>
simulatePopulateChunk(client, kandel, args),
simulateRetract: (args: RetractArgs) =>
simulateRetract(client, kandel, args),
getKandelState: (args: GetKandelStateArgs) =>
getKandelState(client, market, kandel, args),
simulateRetract: (args) => simulateRetract(client, kandel, args),
getKandelState: (args = {}) =>
getKandelState(client, actionParams, market, kandel, args),
})
}
Loading

0 comments on commit 8738527

Please sign in to comment.