Skip to content

Commit

Permalink
feat: add get open order functions
Browse files Browse the repository at this point in the history
  • Loading branch information
graykode committed Apr 5, 2024
1 parent c535bbe commit 9878e5d
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 0 deletions.
29 changes: 29 additions & 0 deletions src/apis/graphql/open-orders.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
query getOpenOrders($userAddress: String!) {
openOrders(where: { user: $userAddress }) {
id
book {
id
base {
id
name
symbol
decimals
}
quote {
id
name
symbol
decimals
}
unit
}
tick
txHash
createdAt

rawAmount
rawFilledAmount
rawClaimedAmount
rawClaimableAmount
}
}
94 changes: 94 additions & 0 deletions src/apis/open-order.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { formatUnits, getAddress, isAddressEqual } from 'viem'

import { getBuiltGraphSDK } from '../.graphclient'
import { CHAIN_IDS } from '../constants/chain'
import { SUBGRAPH_URL } from '../constants/subgraph-url'
import { getMarketId } from '../utils/market'
import { Currency } from '../model/currency'
import { quoteToBase } from '../utils/decimals'
import { formatPrice } from '../utils/prices'
import { invertPrice, toPrice } from '../utils/tick'
import { OpenOrder } from '../model/open-order'

import { fetchCurrency } from './currency'

const { getOpenOrders } = getBuiltGraphSDK()

export async function fetchOpenOrders(
chainId: CHAIN_IDS,
userAddress: `0x${string}`,
): Promise<OpenOrder[]> {
const { openOrders } = await getOpenOrders(
{
userAddress: userAddress.toLowerCase(),
},
{
url: SUBGRAPH_URL[chainId],
},
)
const currencies = await Promise.all(
openOrders
.map((openOrder) => [
getAddress(openOrder.book.base.id),
getAddress(openOrder.book.quote.id),
])
.flat()
.filter(
(address, index, self) =>
self.findIndex((c) => isAddressEqual(c, address)) === index,
)
.map((address) => fetchCurrency(chainId, address)),
)
return openOrders.map((openOrder) => {
const inputCurrency = currencies.find((c: Currency) =>
isAddressEqual(c.address, getAddress(openOrder.book.quote.id)),
)!
const outputCurrency = currencies.find((c: Currency) =>
isAddressEqual(c.address, getAddress(openOrder.book.base.id)),
)!
const { quoteTokenAddress } = getMarketId(chainId, [
inputCurrency.address,
outputCurrency.address,
])
const isBid = isAddressEqual(quoteTokenAddress, inputCurrency.address)
const quote = isBid ? inputCurrency : outputCurrency
const base = isBid ? outputCurrency : inputCurrency
const tick = BigInt(openOrder.tick)
const rawAmount = BigInt(openOrder.rawAmount)
const rawFilledAmount = BigInt(openOrder.rawFilledAmount)
const unit = BigInt(openOrder.book.unit)
const quoteAmount = unit * rawAmount
const rawClaimedAmount = BigInt(openOrder.rawClaimedAmount)
const rawClaimableAmount = BigInt(openOrder.rawClaimableAmount)
const amount = isBid ? quoteToBase(tick, quoteAmount, false) : quoteAmount
const filled = isBid
? quoteToBase(tick, unit * rawFilledAmount, false)
: unit * rawFilledAmount
const claimed = quoteToBase(tick, unit * rawClaimedAmount, false)
const claimable = quoteToBase(tick, unit * rawClaimableAmount, false)
return {
id: BigInt(openOrder.id),
isBid,
inputCurrency,
outputCurrency,
txHash: openOrder.txHash as `0x${string}`,
createdAt: Number(openOrder.createdAt),
price: formatPrice(
isBid ? toPrice(tick) : invertPrice(toPrice(tick)),
quote.decimals,
base.decimals,
),
amount: { currency: base, value: formatUnits(amount, base.decimals) },
filled: { currency: base, value: formatUnits(filled, base.decimals) },
claimed: {
currency: outputCurrency,
value: formatUnits(claimed, outputCurrency.decimals),
},
claimable: {
currency: outputCurrency,
value: formatUnits(claimable, outputCurrency.decimals),
},
cancelable: rawAmount > rawFilledAmount,
}
})
}
16 changes: 16 additions & 0 deletions src/model/open-order.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Currency } from './currency'

export type OpenOrder = {
id: bigint
isBid: boolean
inputCurrency: Currency
outputCurrency: Currency
txHash: `0x${string}`
createdAt: number
price: number
amount: { currency: Currency; value: string }
filled: { currency: Currency; value: string }
claimed: { currency: Currency; value: string }
claimable: { currency: Currency; value: string }
cancelable: boolean
}
1 change: 1 addition & 0 deletions src/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Depth } from './model/depth'
export { CHAIN_IDS } from './constants/chain'
export { Currency } from './model/currency'
export { Depth } from './model/depth'
export { OpenOrder } from './model/open-order'

export type Market = {
chainId: CHAIN_IDS
Expand Down
9 changes: 9 additions & 0 deletions src/view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { CHAIN_IDS } from './constants/chain'
import { Market } from './type'
import { parsePrice } from './utils/prices'
import { MAX_PRICE } from './constants/price'
import { fetchOpenOrders } from './apis/open-order'
import { OpenOrder } from './model/open-order'

/**
* Get market information by chain id and token addresses
Expand Down Expand Up @@ -206,3 +208,10 @@ export const getExpectedInput = async (
),
}
}

export const getOpenOrders = async (
chainId: CHAIN_IDS,
userAddress: `0x${string}`,
): Promise<OpenOrder[]> => {
return fetchOpenOrders(chainId, userAddress)
}
29 changes: 29 additions & 0 deletions test/open-order.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { afterEach, expect, test } from 'vitest'
import { getOpenOrders } from '@clober-dex/v2-sdk'

import { cloberTestChain } from './utils/test-chain'
import { createProxyClients } from './utils/utils'
import { FORK_URL } from './utils/constants'
import { fetchBlockNumer } from './utils/chain'

const clients = createProxyClients([16])

afterEach(async () => {
const blockNumber = await fetchBlockNumer()
await Promise.all(
clients.map(({ testClient }) => {
return testClient.reset({
jsonRpcUrl: FORK_URL,
blockNumber,
})
}),
)
})

test('get open orders by user address', async () => {
const openOrders = await getOpenOrders(
cloberTestChain.id,
'0x5F79EE8f8fA862E98201120d83c4eC39D9468D49',
)
expect(openOrders.length).toBeGreaterThan(0)
})

0 comments on commit 9878e5d

Please sign in to comment.