diff --git a/.changeset/perfect-pigs-repair.md b/.changeset/perfect-pigs-repair.md new file mode 100644 index 0000000..07d94c5 --- /dev/null +++ b/.changeset/perfect-pigs-repair.md @@ -0,0 +1,6 @@ +--- +"@mangrovedao/mgv": minor +--- + +Added routing logics +Added midPrice and spread calculation to getBook diff --git a/src/actions/book.ts b/src/actions/book.ts index 77d7763..eb43dce 100644 --- a/src/actions/book.ts +++ b/src/actions/book.ts @@ -86,21 +86,40 @@ export async function getBook( allowFailure: false, }) + const asks = parseBookResult({ + result: rpcAsks, + ba: BA.asks, + baseDecimals: base.decimals, + quoteDecimals: quote.decimals, + }) + + const bids = parseBookResult({ + result: rpcBids, + ba: BA.bids, + baseDecimals: base.decimals, + quoteDecimals: quote.decimals, + }) + + const midPrice = !asks[0]?.price + ? !bids[0]?.price + ? 0 + : bids[0].price + : (asks[0].price + bids[0].price) / 2 + + const spread = + !asks[0]?.price || !bids[0]?.price ? 0 : asks[0].price - bids[0].price + + const spreadPercent = + !asks[0]?.price || !bids[0]?.price ? 0 : spread / midPrice + return { - asks: parseBookResult({ - result: rpcAsks, - ba: BA.asks, - baseDecimals: base.decimals, - quoteDecimals: quote.decimals, - }), - bids: parseBookResult({ - result: rpcBids, - ba: BA.bids, - baseDecimals: base.decimals, - quoteDecimals: quote.decimals, - }), + asks, + bids, asksConfig: unpackLocalConfig(rpcAsksConfig), bidsConfig: unpackLocalConfig(rpcBaseConfig), marketConfig: unpackGlobalConfig(rpcMarketConfig), + midPrice, + spread, + spreadPercent, } } diff --git a/src/addresses/index.ts b/src/addresses/index.ts index e97ce6e..d493908 100644 --- a/src/addresses/index.ts +++ b/src/addresses/index.ts @@ -17,3 +17,26 @@ export { // --- mangrove --- export { blastMangrove } from './mangrove/index.js' + +// --- logics --- + +export type { + OverlyingParams, + OverlyingResponse, + RoutingLogicOverlying, + LogicBalanceParams, + LogicBalanceResponse, + RoutingLogicBalance, +} from './logics/index.js' + +export { + blastOrbitLogic, + blastZeroLendLogic, + blastPacFinanceLogic, + balanceLogicABI, + baseBalance, + aaveLogicABI, + aaveBalance, + aaveOverLying, + buildLogic, +} from './logics/index.js' diff --git a/src/addresses/logics/chains/blast.ts b/src/addresses/logics/chains/blast.ts new file mode 100644 index 0000000..5942f84 --- /dev/null +++ b/src/addresses/logics/chains/blast.ts @@ -0,0 +1,23 @@ +import { aaveBalance, aaveOverLying } from '../strategies/aave.js' +import { buildLogic } from '../utils.js' + +export const blastOrbitLogic = buildLogic( + 'Orbit', + '0x3870DAFB80713cad59Dd999c85b1E46314b41e9c', + aaveOverLying, + aaveBalance, +) + +export const blastZeroLendLogic = buildLogic( + 'ZeroLend', + '0x5126d161210654148445AdB3053e6DE2bbeaeefB', + aaveOverLying, + aaveBalance, +) + +export const blastPacFinanceLogic = buildLogic( + 'PacFinance', + '0x982A72Afe26C72F7bef644164942BFc1d5D025F8', + aaveOverLying, + aaveBalance, +) diff --git a/src/addresses/logics/chains/index.ts b/src/addresses/logics/chains/index.ts new file mode 100644 index 0000000..394f00b --- /dev/null +++ b/src/addresses/logics/chains/index.ts @@ -0,0 +1,5 @@ +export { + blastOrbitLogic, + blastZeroLendLogic, + blastPacFinanceLogic, +} from './blast.js' diff --git a/src/addresses/logics/index.ts b/src/addresses/logics/index.ts new file mode 100644 index 0000000..e9a0c4a --- /dev/null +++ b/src/addresses/logics/index.ts @@ -0,0 +1,24 @@ +export { + blastOrbitLogic, + blastZeroLendLogic, + blastPacFinanceLogic, +} from './chains/index.js' + +export { + balanceLogicABI, + baseBalance, + aaveLogicABI, + aaveBalance, + aaveOverLying, +} from './strategies/index.js' + +export type { + OverlyingParams, + OverlyingResponse, + RoutingLogicOverlying, + LogicBalanceParams, + LogicBalanceResponse, + RoutingLogicBalance, +} from './utils.js' + +export { buildLogic } from './utils.js' diff --git a/src/addresses/logics/strategies/aave.ts b/src/addresses/logics/strategies/aave.ts new file mode 100644 index 0000000..38dd9b8 --- /dev/null +++ b/src/addresses/logics/strategies/aave.ts @@ -0,0 +1,31 @@ +import { isAddressEqual, parseAbi, zeroAddress } from 'viem' +import type { RoutingLogicOverlying } from '../utils.js' +import { baseBalance } from './base.js' + +export const aaveLogicABI = parseAbi([ + 'function overlying(address asset) public view returns (address aToken)', +]) + +export const aaveOverLying: RoutingLogicOverlying< + typeof aaveLogicABI, + 'view', + 'overlying' +> = { + getOverlyingContractParams(params) { + return { + address: params.token, + abi: aaveLogicABI, + functionName: 'overlying', + args: [params.token], + } + }, + parseOverlyingContractResponse(response) { + return { + type: 'erc20', + token: response, + available: !isAddressEqual(response, zeroAddress), + } + }, +} + +export const aaveBalance = baseBalance diff --git a/src/addresses/logics/strategies/base.ts b/src/addresses/logics/strategies/base.ts new file mode 100644 index 0000000..ee9dee0 --- /dev/null +++ b/src/addresses/logics/strategies/base.ts @@ -0,0 +1,24 @@ +import { parseAbi } from 'viem' +import type { RoutingLogicBalance } from '../utils.js' + +export const balanceLogicABI = parseAbi([ + 'function balanceLogic(address token, address fundOwner) external view returns (uint balance)', +]) + +export const baseBalance: RoutingLogicBalance< + typeof balanceLogicABI, + 'view', + 'balanceLogic' +> = { + getRoutingLogicBalanceParams(params) { + return { + address: params.logic, + abi: balanceLogicABI, + functionName: 'balanceLogic', + args: [params.token, params.user], + } + }, + parseRoutingLogicBalanceResponse(response) { + return response + }, +} diff --git a/src/addresses/logics/strategies/index.ts b/src/addresses/logics/strategies/index.ts new file mode 100644 index 0000000..a5ff141 --- /dev/null +++ b/src/addresses/logics/strategies/index.ts @@ -0,0 +1,10 @@ +export { + balanceLogicABI, + baseBalance, +} from './base.js' + +export { + aaveLogicABI, + aaveOverLying, + aaveBalance, +} from './aave.js' diff --git a/src/addresses/logics/utils.ts b/src/addresses/logics/utils.ts new file mode 100644 index 0000000..50af71a --- /dev/null +++ b/src/addresses/logics/utils.ts @@ -0,0 +1,98 @@ +import type { + Abi, + AbiStateMutability, + Address, + ContractFunctionName, + ContractFunctionParameters, + ContractFunctionReturnType, +} from 'viem' + +export type OverlyingParams = { + token: Address + logic: Address + name: string +} + +export type OverlyingResponse = { + type: 'erc20' | 'erc721' + token: Address + available: boolean +} + +export type RoutingLogicOverlying< + abi extends Abi | readonly unknown[] = Abi, + mutability extends AbiStateMutability = AbiStateMutability, + functionName extends ContractFunctionName< + abi, + mutability + > = ContractFunctionName, +> = { + getOverlyingContractParams: ( + params: OverlyingParams, + ) => ContractFunctionParameters + parseOverlyingContractResponse: ( + response: ContractFunctionReturnType, + ) => OverlyingResponse +} + +export type LogicBalanceParams = { + token: Address + logic: Address + name: string + user: Address +} + +export type LogicBalanceResponse = bigint + +export type RoutingLogicBalance< + abi extends Abi | readonly unknown[] = Abi, + mutability extends AbiStateMutability = AbiStateMutability, + functionName extends ContractFunctionName< + abi, + mutability + > = ContractFunctionName, +> = { + getRoutingLogicBalanceParams: ( + params: LogicBalanceParams, + ) => ContractFunctionParameters + parseRoutingLogicBalanceResponse: ( + response: ContractFunctionReturnType, + ) => LogicBalanceResponse +} + +export function buildLogic< + TName extends string = string, + TLogicAddress extends Address = Address, + abiOverlying extends Abi | readonly unknown[] = Abi, + mutabilityOverlying extends AbiStateMutability = AbiStateMutability, + functionNameOverlying extends ContractFunctionName< + abiOverlying, + mutabilityOverlying + > = ContractFunctionName, + abiBalance extends Abi | readonly unknown[] = Abi, + mutabilityBalance extends AbiStateMutability = AbiStateMutability, + functionNameBalance extends ContractFunctionName< + abiBalance, + mutabilityBalance + > = ContractFunctionName, +>( + name: TName, + logic: TLogicAddress, + logicOverlying: RoutingLogicOverlying< + abiOverlying, + mutabilityOverlying, + functionNameOverlying + >, + logicBalance: RoutingLogicBalance< + abiBalance, + mutabilityBalance, + functionNameBalance + >, +) { + return { + name, + logic, + logicOverlying, + logicBalance, + } +} diff --git a/src/index.ts b/src/index.ts index 6410a51..e6426ee 100644 --- a/src/index.ts +++ b/src/index.ts @@ -68,4 +68,10 @@ export { publicMarketActions } from './bundle/index.js' export type { Token, BuildTokenParms, + OverlyingParams, + OverlyingResponse, + RoutingLogicOverlying, + LogicBalanceParams, + LogicBalanceResponse, + RoutingLogicBalance, } from './addresses/index.js' diff --git a/src/types/actions/book.ts b/src/types/actions/book.ts index 686e824..7834645 100644 --- a/src/types/actions/book.ts +++ b/src/types/actions/book.ts @@ -15,6 +15,9 @@ export type BookParams = { * @param asksConfig the asks semibook configuration * @param bidsConfig the bids semibook configuration * @param marketConfig the global mangrove configuration + * @param midPrice the mid price + * @param spread the spread + * @param spreadPercent the spread percent */ export type Book = { asks: CompleteOffer[] @@ -22,4 +25,7 @@ export type Book = { asksConfig: LocalConfig bidsConfig: LocalConfig marketConfig: GlobalConfig + midPrice: number + spread: number + spreadPercent: number }