Skip to content

Commit

Permalink
updates
Browse files Browse the repository at this point in the history
  • Loading branch information
FinnCF committed May 12, 2024
1 parent b642cbe commit 6e70052
Showing 1 changed file with 172 additions and 48 deletions.
220 changes: 172 additions & 48 deletions pages/api/tokentiers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,42 @@ import { AnchorProvider, Wallet } from '@coral-xyz/anchor'
import { Connection, PublicKey, Keypair } from '@solana/web3.js'
import { LISTING_PRESETS } from '@blockworks-foundation/mango-v4-settings/lib/helpers/listingTools'

// Utility to build a MangoClient instance
interface TokenDetails {
reduceOnly?: number
maxBelow1Percent: { amount: number; preset: string }
maxBelow2Percent: { amount: number; preset: string }
initAssetWeight?: string
maintAssetWeight?: string
maintLiabWeight?: string
initLiabWeight?: string
mint?: string
currentTier?: string
collateralFeesPerDay?: number
}

interface CurrentTier {
name: string
reduceOnly?: number
maxBelow1PercentAmount?: number
maxBelow1PercentPreset?: string
maxBelow2PercentAmount?: number
maxBelow2PercentPreset?: string
initAssetWeight?: string
maintAssetWeight?: string
maintLiabWeight?: string
initLiabWeight?: string
mint?: string
currentTier?: string
collateralFeesPerDay?: number
}

type CurrentTiersResponse = CurrentTier[]

async function buildClient(): Promise<MangoClient> {
const clientKeypair = new Keypair()
const options = AnchorProvider.defaultOptions()

const rpcUrl = process.env.NEXT_PUBLIC_RPC_URL // replace with ENV
const rpcUrl = process.env.NEXT_PUBLIC_RPC_URL
if (!rpcUrl) {
throw new Error('MANGO_RPC_URL environment variable is not set')
}
Expand All @@ -18,20 +48,19 @@ async function buildClient(): Promise<MangoClient> {
const clientWallet = new Wallet(clientKeypair)
const clientProvider = new AnchorProvider(connection, clientWallet, options)

return await MangoClient.connect(
return MangoClient.connect(
clientProvider,
'mainnet-beta',
new PublicKey('4MangoMjqJ2firMokCjjGgoK8d4MXcrgL7XJaL3w6fVg'),
{
idsSource: 'get-program-accounts',
},
{ idsSource: 'get-program-accounts' },
)
}

// API handler function
export default async function handler(
req: NextApiRequest,
res: NextApiResponse,
res: NextApiResponse<
CurrentTiersResponse | { error: string; details: string }
>,
) {
try {
const client = await buildClient()
Expand All @@ -40,56 +69,151 @@ export default async function handler(
)

const banks = Array.from(group.banksMapByTokenIndex.values())
.map((banks) => banks[0])
.map((bank) => bank[0])
.sort((a, b) => a.name.localeCompare(b.name))

const currentTiers: Array<{ [key: string]: string }> = []
const epsilon = 1e-8
const priceImpacts = group?.pis || []
const tokenThresholds: {
[symbol: string]: { below1Percent: number; below2Percent: number }
} = {}

for (const impact of priceImpacts) {
if (!tokenThresholds[impact.symbol]) {
tokenThresholds[impact.symbol] = { below1Percent: 0, below2Percent: 0 }
}
if (
impact.avg_price_impact_percent < 1 &&
impact.target_amount > tokenThresholds[impact.symbol].below1Percent
) {
tokenThresholds[impact.symbol].below1Percent = impact.target_amount
}
if (
impact.avg_price_impact_percent < 2 &&
impact.target_amount > tokenThresholds[impact.symbol].below2Percent
) {
tokenThresholds[impact.symbol].below2Percent = impact.target_amount
}
}

const newRankings: { [symbol: string]: TokenDetails } = {}

for (const [, preset] of Object.entries(LISTING_PRESETS)) {
for (const [symbol, thresholds] of Object.entries(tokenThresholds)) {
if (!newRankings[symbol]) {
newRankings[symbol] = {
maxBelow1Percent: { amount: 0, preset: 'C' },
maxBelow2Percent: { amount: 0, preset: 'C' },
}
}

if (preset.preset_target_amount <= thresholds.below1Percent) {
if (
preset.preset_target_amount >=
newRankings[symbol].maxBelow1Percent.amount
) {
newRankings[symbol].maxBelow1Percent = {
amount: preset.preset_target_amount,
preset: preset.preset_name,
}
}
}

if (preset.preset_target_amount <= thresholds.below2Percent) {
if (
preset.preset_target_amount >=
newRankings[symbol].maxBelow2Percent.amount
) {
newRankings[symbol].maxBelow2Percent = {
amount: preset.preset_target_amount,
preset: preset.preset_name,
}
}
}
}
}

await Promise.all(
banks.map(async (bank) => {
if (bank?.reduceOnly != 1) {
const currentTier = Object.values(LISTING_PRESETS).find((x) => {
if (bank?.name == 'USDC' || bank?.name == 'USDT') return false
if (bank?.depositWeightScaleStartQuote != 20000000000) {
if (
x.depositWeightScaleStartQuote ===
bank?.depositWeightScaleStartQuote
) {
return true
}
} else {
return (
Math.abs(
x.loanOriginationFeeRate -
bank?.loanOriginationFeeRate.toNumber(),
) < epsilon
)
}
})
currentTiers.push({
[bank?.name]: currentTier?.preset_name
? currentTier?.preset_name
: 'S',
})
return bank
const currentTier = Object.values(LISTING_PRESETS).find((x) => {
if (bank?.platformLiquidationFee.toNumber() === 0) {
return (
x.platformLiquidationFee.toFixed(2) ===
bank?.platformLiquidationFee.toNumber().toFixed(2)
)
}
if (bank?.initAssetWeight.toNumber() === 0) {
return (
x.maintLiabWeight.toFixed(2) ===
bank?.maintLiabWeight.toNumber().toFixed(2)
)
}
if (bank?.depositWeightScaleStartQuote !== 20000000000) {
return (
x.depositWeightScaleStartQuote ===
bank?.depositWeightScaleStartQuote
)
} else {
return (
Math.abs(
x.loanOriginationFeeRate -
bank?.loanOriginationFeeRate.toNumber(),
) < 1e-8
)
}
})

let bankName = bank?.name
if (bankName === 'WIF') bankName = '$WIF'
if (bankName === 'ETH (Portal)') bankName = 'ETH'
if (bank?.mint && newRankings[bankName]) {
newRankings[bankName].reduceOnly = bank?.reduceOnly
newRankings[bankName].currentTier = currentTier?.preset_name || 'S'
newRankings[bankName].mint = bank?.mint.toString()
newRankings[bankName].initAssetWeight = bank?.initAssetWeight
.toNumber()
.toFixed(2)
newRankings[bankName].maintAssetWeight = bank?.maintAssetWeight
.toNumber()
.toFixed(2)
newRankings[bankName].maintLiabWeight = bank?.maintLiabWeight
.toNumber()
.toFixed(2)
newRankings[bankName].initLiabWeight = bank?.initLiabWeight
.toNumber()
.toFixed(2)
newRankings[bankName].collateralFeesPerDay = bank?.collateralFeePerDay
}
}),
)

res.status(200.0).json(currentTiers)
const currentTiers: CurrentTiersResponse = Object.entries(newRankings).map(
([name, details]) => ({
name,
reduceOnly: details.reduceOnly,
maxBelow1PercentAmount: details.maxBelow1Percent.amount,
maxBelow1PercentPreset: details.maxBelow1Percent.preset,
maxBelow2PercentAmount: details.maxBelow2Percent.amount,
maxBelow2PercentPreset: details.maxBelow2Percent.preset,
initAssetWeight: details.initAssetWeight,
maintAssetWeight: details.maintAssetWeight,
maintLiabWeight: details.maintLiabWeight,
initLiabWeight: details.initLiabWeight,
mint: details.mint,
currentTier: details.currentTier,
collateralFeesPerDay: details.collateralFeesPerDay,
}),
)

res.status(200).json(currentTiers)
} catch (error: unknown) {
console.error('Failed to fetch tokens:', error)
let errorMessage = 'An unexpected error occurred'
if (error instanceof Error) {
res
.status(500)
.json({ error: 'Failed to fetch tokens', details: error.message })
} else {
res
.status(500)
.json({
error: 'Failed to fetch tokens',
details: 'An unexpected error occurred',
})
errorMessage = error.message
}

console.error('Failed to fetch tokens:', error)
res
.status(500)
.json({ error: 'Failed to fetch tokens', details: errorMessage })
}
}

0 comments on commit 6e70052

Please sign in to comment.