Skip to content

Commit

Permalink
Merge pull request #80 from Premian-Labs/issue/remove-most-liquid
Browse files Browse the repository at this point in the history
Remove mostLiquidOptionForToken[Pair] as it belongs in FE
  • Loading branch information
froggiedev committed Dec 6, 2023
2 parents fa4be21 + cef4b6a commit 6fe6b09
Show file tree
Hide file tree
Showing 3 changed files with 4 additions and 290 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@premia/v3-sdk",
"version": "1.2.2",
"version": "1.3.0",
"description": "The official SDK for building applications on Premia V3.",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
Expand Down
291 changes: 3 additions & 288 deletions src/api/optionAPI.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,14 @@
import { BigNumberish, ZeroAddress, parseEther, toBigInt } from 'ethers'
import { BigNumberish, toBigInt } from 'ethers'
import { get, isEqual } from 'lodash'

import { withCache } from '../cache'
import { CacheTTL, WAD_DECIMALS, ZERO_BI } from '../constants'
import {
FillableQuote,
OptionType,
Pool,
PoolMinimal,
Token,
VaultTradeSide,
} from '../entities'
import { FillableQuote, PoolMinimal, Token } from '../entities'
import { BaseAPI } from './baseAPI'
import { TokenOrAddress } from './tokenAPI'
import { roundToNearest } from '../utils/round'
import { parseBigInt, parseNumber } from '../utils'
import {
Addresses,
ONE_YEAR_MS,
TokenPairOrId,
WAD_BI,
blackScholes,
convertDecimals,
} from '../'
import { ONE_YEAR_MS, blackScholes } from '../'

/**
* This class provides an API for interacting with options in the Premia system.
Expand Down Expand Up @@ -237,277 +223,6 @@ export class OptionAPI extends BaseAPI {
return iv
}

/**
* Gets the most liquid option for the specified base token.
* The liquidity is calculated using pool and vault liquidity.
*
* @returns {Promise<PoolMinimal | null>} The Pool representing the most liquid option or null if no options exist.
*/
@withCache(CacheTTL.HOURLY)
async getMostLiquidOptionForToken(
baseAddress: string,
options: {
isCall: boolean
isBuy: boolean
maturity?: BigNumberish
strike?: BigNumberish
showErrors?: boolean
}
): Promise<Pool | null> {
let pools = await this.premia.pools.getPools(baseAddress, false)

pools = pools.filter((p) => p.isCall === options.isCall)

if (options.maturity) {
pools = pools.filter(
(p) => String(p.maturity) === String(options.maturity)
)
}

if (options.strike) {
pools = pools.filter((p) => String(p.strike) === String(options.strike))
}

if (options.isBuy) {
const token = options.isCall
? baseAddress
: Addresses[this.premia.chainId].USDC

const prefilter = await this.premia.vaults.getVaultsExtendedForToken(
token
)

const vaults = prefilter.filter(
(v) =>
[VaultTradeSide.Sell, VaultTradeSide.Both].includes(v.side) &&
v.optionType === (options.isCall ? OptionType.CALL : OptionType.PUT)
)

const willTrade = await Promise.all(
vaults.map(async (vault) => {
if (!options.isBuy) return pools.map(() => false)

const vaultContract = this.premia.contracts.getVaultContract(
vault.address,
this.premia.multicallProvider
)

return await Promise.all(
pools.map(async (pool) => {
try {
const poolKey = await this.premia.pools.getPoolKeyFromAddress(
pool.address
)
const quote = await vaultContract.getQuote(
poolKey,
parseEther('0.0001'),
options.isBuy,
ZeroAddress
)
return quote > 0n
} catch (err) {
if (options.showErrors) {
console.log(
'Vault + Pool failed: ',
vault.name,
pool.name,
err
)
}

return false
}
})
)
})
)

const vaultSizes = vaults.map((vault) =>
convertDecimals(
toBigInt(vault.totalAvailable),
vault.asset.decimals,
WAD_DECIMALS
)
)

return pools.reduce((prev: Pool | null, curr: Pool, poolIndex) => {
if (prev == null) return curr

const prevVaultSize = vaultSizes.reduce((a, b, index) => {
return willTrade[index][pools.indexOf(prev)] ? a + b : a
}, 0n)

const vaultSize = vaultSizes.reduce((a, b, index) => {
return willTrade[index][poolIndex] ? a + b : a
}, 0n)

const prevSize =
toBigInt((prev as Pool).shortLiquidity) +
(options.isCall
? prevVaultSize
: (prevVaultSize * WAD_BI) / toBigInt(prev.strike))
const currSize =
toBigInt(curr.shortLiquidity) +
(options.isCall
? vaultSize
: (vaultSize * WAD_BI) / toBigInt(curr.strike))

if (prev != null && prevSize > currSize) {
return prev
}

return curr
}, null)
} else {
return pools.reduce((prev: Pool | null, curr: Pool) => {
if (
prev != null &&
toBigInt((prev as Pool).longLiquidity) > toBigInt(curr.longLiquidity)
) {
return prev
}

return curr
}, null)
}
}

/**
* Gets the most liquid option for the specified token pair.
* The liquidity is calculated using pool and vault liquidity.
*
* @returns {Promise<PoolMinimal | null>} The Pool representing the most liquid option or null if no options exist.
*/
@withCache(CacheTTL.HOURLY)
async getMostLiquidOptionForTokenPair(
pair: TokenPairOrId,
options: {
isCall: boolean
isBuy: boolean
maturity?: BigNumberish
strike?: BigNumberish
showErrors?: boolean
}
): Promise<PoolMinimal | null> {
let [tokenPair, pools] = await Promise.all([
this.premia.pairs.getPair(pair),
this.premia.pools.getPoolsForPair(pair, false),
])

pools = pools.filter((p) => p.isCall === options.isCall)

if (options.maturity) {
pools = pools.filter(
(p) => String(p.maturity) === String(options.maturity)
)
}

if (options.strike) {
pools = pools.filter((p) => String(p.strike) === String(options.strike))
}

if (options.isBuy) {
const token = options.isCall ? tokenPair.base : tokenPair.quote

const prefilter = await this.premia.vaults.getVaultsExtendedForToken(
token
)

const vaults = prefilter.filter(
(v) =>
[VaultTradeSide.Sell, VaultTradeSide.Both].includes(v.side) &&
v.optionType === (options.isCall ? OptionType.CALL : OptionType.PUT)
)

const willTrade = await Promise.all(
vaults.map(async (vault) => {
if (!options.isBuy) return pools.map(() => false)

const vaultContract = this.premia.contracts.getVaultContract(
vault.address,
this.premia.multicallProvider
)

return await Promise.all(
pools.map(async (pool) => {
try {
const poolKey = await this.premia.pools.getPoolKeyFromAddress(
pool.address
)
const quote = await vaultContract.getQuote(
poolKey,
parseEther('0.0001'),
options.isBuy,
ZeroAddress
)
return quote > 0n
} catch (err) {
if (options.showErrors) {
console.log(
'Vault + Pool failed: ',
vault.name,
pool.name,
err
)
}

return false
}
})
)
})
)

const vaultSizes = vaults.map((vault) =>
convertDecimals(
toBigInt(vault.totalAvailable),
vault.asset.decimals,
WAD_DECIMALS
)
)

return pools.reduce((prev: Pool | null, curr: Pool, poolIndex) => {
if (prev == null) return curr

const prevVaultSize = vaultSizes.reduce((a, b, index) => {
return willTrade[index][pools.indexOf(prev)] ? a + b : a
}, 0n)

const vaultSize = vaultSizes.reduce((a, b, index) => {
return willTrade[index][poolIndex] ? a + b : a
}, 0n)

const prevSize =
toBigInt((prev as Pool).shortLiquidity) +
(options.isCall
? prevVaultSize
: (prevVaultSize * WAD_BI) / toBigInt(prev.strike))
const currSize =
toBigInt(curr.shortLiquidity) +
(options.isCall
? vaultSize
: (vaultSize * WAD_BI) / toBigInt(curr.strike))

if (prev != null && prevSize > currSize) {
return prev
}

return curr
}, null)
} else {
return pools.reduce((prev: Pool | null, curr: Pool) => {
if (
prev != null &&
toBigInt((prev as Pool).longLiquidity) > toBigInt(curr.longLiquidity)
) {
return prev
}

return curr
}, null)
}
}

/**
* Provides the best quote available from different sources (RFQ, Pool, Vault) based on the provided options.
* The method is cached for a second to improve performance.
Expand Down
1 change: 0 additions & 1 deletion src/api/poolAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
ContractTransactionResponse,
FixedNumber,
getAddress,
parseEther,
toBigInt,
ZeroAddress,
} from 'ethers'
Expand Down

0 comments on commit 6fe6b09

Please sign in to comment.