Skip to content

Commit

Permalink
Merge pull request #111 from clober-dex/feat/add-mm-vault-tests
Browse files Browse the repository at this point in the history
feat: mm vault tests
  • Loading branch information
Dorvin authored Sep 27, 2024
2 parents 52b5ca9 + 5d74712 commit 5a87f19
Show file tree
Hide file tree
Showing 16 changed files with 739 additions and 50 deletions.
54 changes: 54 additions & 0 deletions examples/pool/set-strategy-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import * as dotenv from 'dotenv'
import {
createPublicClient,
createWalletClient,
http,
parseUnits,
zeroHash,
} from 'viem'
import { arbitrumSepolia } from 'viem/chains'
import { privateKeyToAccount } from 'viem/accounts'

import { setStrategyConfig } from '../../src'

dotenv.config()

const main = async () => {
const walletClient = createWalletClient({
chain: arbitrumSepolia,
account: privateKeyToAccount(
(process.env.OWNER_PRIVATE_KEY || '0x') as `0x${string}`,
),
transport: http(),
})
const publicClient = createPublicClient({
chain: arbitrumSepolia,
transport: http(),
})

const transaction = await setStrategyConfig({
chainId: arbitrumSepolia.id,
userAddress: walletClient.account.address,
token0: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
token1: '0xF2e615A933825De4B39b497f6e6991418Fb31b78',
salt: zeroHash,
config: {
referenceThreshold: '0.1',
rateA: '0.1',
rateB: '0.1',
minRateA: '0.003',
minRateB: '0.003',
priceThresholdA: '0.1',
priceThresholdB: '0.1',
},
})

const hash = await walletClient.sendTransaction({
...transaction,
gasPrice: parseUnits('1', 9),
})
await publicClient.waitForTransactionReceipt({ hash: hash })
console.log(`set config hash: ${hash}`)
}

main()
33 changes: 14 additions & 19 deletions src/apis/pool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { CHAIN_IDS } from '../constants/chain'
import { Pool } from '../model/pool'
import { CONTRACT_ADDRESSES } from '../constants/addresses'
import { toPoolKey } from '../utils/pool-key'
import { fetchOnChainOrders } from '../utils/order'
import { REBALANCER_ABI } from '../abis/rebalancer/rebalancer-abi'
import { Market } from '../type'

import { fetchMarket } from './market'

Expand All @@ -15,17 +15,21 @@ export async function fetchPool(
tokenAddresses: `0x${string}`[],
salt: `0x${string}`,
useSubgraph: boolean,
market?: Market,
): Promise<Pool> {
if (tokenAddresses.length !== 2) {
throw new Error('Invalid token pair')
}
const market = await fetchMarket(
publicClient,
chainId,
tokenAddresses,
useSubgraph,
if (!market) {
market = (
await fetchMarket(publicClient, chainId, tokenAddresses, useSubgraph)
).toJson()
}
const poolKey = toPoolKey(
BigInt(market.bidBook.id),
BigInt(market.askBook.id),
salt,
)
const poolKey = toPoolKey(market.bidBook.id, market.askBook.id, salt)
const [
{ bookIdA, bookIdB, reserveA, reserveB, orderListA, orderListB },
totalSupply,
Expand Down Expand Up @@ -61,12 +65,6 @@ export async function fetchPool(
totalLiquidityB.reserve +
totalLiquidityB.cancelable +
totalLiquidityB.claimable
const orders = await fetchOnChainOrders(
publicClient,
chainId,
[...orderListA, ...orderListB],
useSubgraph,
)
return new Pool({
chainId,
market,
Expand All @@ -76,10 +74,7 @@ export async function fetchPool(
salt,
poolKey,
totalSupply: BigInt(totalSupply),
decimals:
market.base.decimals > market.quote.decimals
? market.base.decimals
: market.quote.decimals,
decimals: 18,
liquidityA: BigInt(liquidityA),
liquidityB: BigInt(liquidityB),
cancelableA: BigInt(totalLiquidityA.cancelable),
Expand All @@ -88,7 +83,7 @@ export async function fetchPool(
claimableB: BigInt(totalLiquidityB.claimable),
reserveA: BigInt(reserveA),
reserveB: BigInt(reserveB),
orderListA: orders.filter((order) => orderListA.includes(BigInt(order.id))),
orderListB: orders.filter((order) => orderListB.includes(BigInt(order.id))),
orderListA: orderListA.map((id: bigint) => BigInt(id)),
orderListB: orderListB.map((id: bigint) => BigInt(id)),
})
}
150 changes: 135 additions & 15 deletions src/call.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import { emptyERC20PermitParams } from './constants/permit'
import { abs } from './utils/math'
import { toBytes32 } from './utils/pool-key'
import { OPERATOR_ABI } from './abis/rebalancer/operator-abi'
import { STRATEGY_ABI } from './abis/rebalancer/strategy-abi'

/**
* Build a transaction to open a market.
Expand Down Expand Up @@ -1470,7 +1471,7 @@ export const removeLiquidity = async ({
}
}

export const rebalance = async ({
export const refillOrder = async ({
chainId,
userAddress,
token0,
Expand Down Expand Up @@ -1526,15 +1527,15 @@ export const rebalance = async ({
)
}

export const updateStrategyPrice = async ({
export const adjustOrderPrice = async ({
chainId,
userAddress,
token0,
token1,
salt,
oraclePrice,
priceA,
priceB,
bidPrice,
askPrice,
alpha,
options,
}: {
Expand All @@ -1544,20 +1545,26 @@ export const updateStrategyPrice = async ({
token1: `0x${string}`
salt: `0x${string}`
oraclePrice: string // price with currencyA as quote
priceA: string // price with currencyA as quote
priceB: string // price when currencyA as quote
bidPrice: string // price with bookA. bid price
askPrice: string // price with bookA. ask price
alpha: string // alpha value, 0 < alpha <= 1
options?: {
tickA?: bigint
tickB?: bigint
roundingUpPriceA?: boolean
roundingUpPriceB?: boolean
roundingUpBidPrice?: boolean
roundingUpAskPrice?: boolean
useSubgraph?: boolean
} & DefaultWriteContractOptions
}): Promise<Transaction> => {
if (Number(alpha) <= 0 || Number(alpha) > 1) {
throw new Error('Alpha value must be in the range (0, 1]')
}
if (Number(bidPrice) <= 0 || Number(askPrice) <= 0) {
throw new Error('Price must be greater than 0')
}
if (Number(bidPrice) >= Number(askPrice)) {
throw new Error('Bid price must be less than ask price')
}
const publicClient = createPublicClient({
chain: CHAIN_MAP[chainId],
transport: options?.rpcUrl ? http(options.rpcUrl) : http(),
Expand All @@ -1582,23 +1589,23 @@ export const updateStrategyPrice = async ({
})
`)
}
const [roundingUpPriceA, roundingUpPriceB] = [
options?.roundingUpPriceA ? options.roundingUpPriceA : false,
options?.roundingUpPriceB ? options.roundingUpPriceB : false,
const [roundingUpBidPrice, roundingUpAskPrice] = [
options?.roundingUpBidPrice ? options.roundingUpBidPrice : false,
options?.roundingUpAskPrice ? options.roundingUpAskPrice : false,
]
const {
roundingDownTick: roundingDownTickA,
roundingUpTick: roundingUpTickA,
} = parsePrice(
Number(priceA),
Number(bidPrice),
pool.currencyA.decimals,
pool.currencyB.decimals,
)
const {
roundingDownTick: roundingDownTickB,
roundingUpTick: roundingUpTickB,
} = parsePrice(
Number(priceB),
Number(askPrice),
pool.currencyA.decimals,
pool.currencyB.decimals,
)
Expand All @@ -1610,10 +1617,12 @@ export const updateStrategyPrice = async ({
)
const tickA = options?.tickA
? Number(options.tickA)
: Number(roundingUpPriceA ? roundingUpTickA : roundingDownTickA)
: Number(roundingUpBidPrice ? roundingUpTickA : roundingDownTickA)
const tickB = options?.tickB
? Number(options.tickB)
: Number(invertTick(roundingUpPriceB ? roundingUpTickB : roundingDownTickB))
: Number(
invertTick(roundingUpAskPrice ? roundingUpTickB : roundingDownTickB),
)

const alphaRaw = parseUnits(alpha, 6)

Expand All @@ -1630,3 +1639,114 @@ export const updateStrategyPrice = async ({
options?.gasLimit,
)
}

export const setStrategyConfig = async ({
chainId,
userAddress,
token0,
token1,
salt,
config,
options,
}: {
chainId: CHAIN_IDS
userAddress: `0x${string}`
token0: `0x${string}`
token1: `0x${string}`
salt: `0x${string}`
config: {
referenceThreshold: string // 0 <= referenceThreshold <= 1
rateA: string // 0 <= rateA <= 1
rateB: string // 0 <= rateB <= 1
minRateA: string // 0 <= minRateA <= rateA
minRateB: string // 0 <= minRateB <= rateB
priceThresholdA: string // 0 <= priceThresholdA <= 1
priceThresholdB: string // 0 <= priceThresholdB <= 1
}
options?: {
useSubgraph?: boolean
} & DefaultWriteContractOptions
}): Promise<Transaction> => {
// validate config
if (
Number(config.referenceThreshold) < 0 ||
Number(config.referenceThreshold) > 1
) {
throw new Error('Reference threshold must be in the range [0, 1]')
}
if (
Number(config.priceThresholdA) < 0 ||
Number(config.priceThresholdA) > 1 ||
Number(config.priceThresholdB) < 0 ||
Number(config.priceThresholdB) > 1
) {
throw new Error('Price threshold must be in the range [0, 1]')
}
if (
Number(config.rateA) < 0 ||
Number(config.rateA) > 1 ||
Number(config.rateB) < 0 ||
Number(config.rateB) > 1
) {
throw new Error('Rate must be in the range [0, 1]')
}
if (
Number(config.minRateA) < 0 ||
Number(config.minRateA) > 1 ||
Number(config.minRateB) < 0 ||
Number(config.minRateB) > 1
) {
throw new Error('Min rate must be in the range [0, 1]')
}
if (
Number(config.minRateA) > Number(config.rateA) ||
Number(config.minRateB) > Number(config.rateB)
) {
throw new Error('Min rate must be less or equal to rate')
}
const publicClient = createPublicClient({
chain: CHAIN_MAP[chainId],
transport: options?.rpcUrl ? http(options.rpcUrl) : http(),
})
const pool = await fetchPool(
publicClient,
chainId,
[token0, token1],
salt,
!!(options && options.useSubgraph),
)
if (!pool.isOpened) {
throw new Error(`
Open the pool before set strategy config.
import { openPool } from '@clober/v2-sdk'
const transaction = await openPool({
chainId: ${chainId},
tokenA: '${token0}',
tokenB: '${token1}',
})
`)
}

const configRaw = {
referenceThreshold: parseUnits(config.referenceThreshold, 6),
rateA: parseUnits(config.rateA, 6),
rateB: parseUnits(config.rateB, 6),
minRateA: parseUnits(config.minRateA, 6),
minRateB: parseUnits(config.minRateB, 6),
priceThresholdA: parseUnits(config.priceThresholdA, 6),
priceThresholdB: parseUnits(config.priceThresholdB, 6),
}
return buildTransaction(
publicClient,
{
chain: CHAIN_MAP[chainId],
account: userAddress,
address: CONTRACT_ADDRESSES[chainId]!.Strategy,
abi: STRATEGY_ABI,
functionName: 'setConfig',
args: [pool.key, configRaw],
},
options?.gasLimit,
)
}
9 changes: 9 additions & 0 deletions src/constants/addresses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ export const CONTRACT_ADDRESSES: {
Minter: getAddress('0xF2f51B00C2e9b77F23fD66649bbabf8a025c39eF'),
Operator: getAddress('0x33559576B062D08230b467ea7DC7Ce75aFcbdE92'),
},
[CHAIN_IDS.CLOBER_TESTNET_2]: {
Controller: getAddress('0xFbbA685a39bE6640B8EB08c6E6DDf2664fD1D668'),
BookManager: getAddress('0xC528b9ED5d56d1D0d3C18A2342954CE1069138a4'),
BookViewer: getAddress('0x73c524e103C94Bf2743659d739586395B1A9e1BE'),
Rebalancer: getAddress('0xCF556d850277BC579c99C0729F4E72e62C57D811'),
Strategy: getAddress('0x8aDF62b0b6078EaE5a2D54e9e5DD2AA71F6748C4'),
Minter: getAddress('0xF2f51B00C2e9b77F23fD66649bbabf8a025c39eF'),
Operator: getAddress('0x33559576B062D08230b467ea7DC7Ce75aFcbdE92'),
},
[CHAIN_IDS.ARBITRUM_SEPOLIA]: {
Controller: getAddress('0xFbbA685a39bE6640B8EB08c6E6DDf2664fD1D668'),
BookManager: getAddress('0xC528b9ED5d56d1D0d3C18A2342954CE1069138a4'),
Expand Down
5 changes: 4 additions & 1 deletion src/constants/chain.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { arbitrumSepolia, base, type Chain, zkSync } from 'viem/chains'

import { cloberTestChain } from './test-chain'
import { cloberTestChain, cloberTestChain2 } from './test-chain'
import { berachainBartioTestnet } from './bera-bartio-chain'

export enum CHAIN_IDS {
CLOBER_TESTNET = cloberTestChain.id,
CLOBER_TESTNET_2 = cloberTestChain2.id,
ARBITRUM_SEPOLIA = arbitrumSepolia.id,
BASE = base.id,
BERACHAIN_TESTNET = berachainBartioTestnet.id,
Expand All @@ -15,6 +16,7 @@ export const CHAIN_MAP: {
[chain in CHAIN_IDS]: Chain
} = {
[CHAIN_IDS.CLOBER_TESTNET]: cloberTestChain,
[CHAIN_IDS.CLOBER_TESTNET_2]: cloberTestChain2,
[CHAIN_IDS.ARBITRUM_SEPOLIA]: arbitrumSepolia,
[CHAIN_IDS.BASE]: base,
[CHAIN_IDS.BERACHAIN_TESTNET]: berachainBartioTestnet,
Expand All @@ -23,5 +25,6 @@ export const CHAIN_MAP: {

export const isTestnetChain = (chainId: CHAIN_IDS): boolean =>
chainId === CHAIN_IDS.CLOBER_TESTNET ||
chainId === CHAIN_IDS.CLOBER_TESTNET_2 ||
chainId === CHAIN_IDS.ARBITRUM_SEPOLIA ||
chainId === CHAIN_IDS.BERACHAIN_TESTNET
Loading

0 comments on commit 5a87f19

Please sign in to comment.