diff --git a/src/api/reserve/config/addresses.config.ts b/src/api/reserve/config/addresses.config.ts index e1d039b..c9554b3 100644 --- a/src/api/reserve/config/addresses.config.ts +++ b/src/api/reserve/config/addresses.config.ts @@ -81,14 +81,6 @@ export const RESERVE_ADDRESS_CONFIGS: ReserveAddressConfig[] = [ assets: ['CELO', 'USDT'], description: 'Reserve assets held in the Aave protocol', }, - { - address: '0x619600F4ec13C38868841cB83100F611eCF94eE8', - chain: Chain.CELO, - category: AddressCategory.MENTO_RESERVE, - label: 'Falcon Finance Custodied Funds', - assets: ['CELO'], - description: 'Reserve assets custodied by Falcon Finance', - }, { address: '0xaa8299fc6a685b5f9ce9bda8d0b3ea3d54731976', chain: Chain.CELO, diff --git a/src/api/v2/config/reserve-addresses.config.ts b/src/api/v2/config/reserve-addresses.config.ts index f1ba621..361357c 100644 --- a/src/api/v2/config/reserve-addresses.config.ts +++ b/src/api/v2/config/reserve-addresses.config.ts @@ -17,37 +17,26 @@ export type CustodianType = 'hot' | 'cold' | 'ops'; export interface ReserveAddress { address: string; - chain: Chain; + chains: Chain[]; label: string; custodianType: CustodianType; + description?: string; } /* prettier-ignore */ export const RESERVE_ADDRESSES: ReserveAddress[] = [ - // --- Celo --- - { address: '0x9380fA34Fd9e4Fd14c06305fd7B6199089eD4eb9', chain: Chain.CELO, label: 'Mento Pools Liquidity Reserve', custodianType: 'hot' }, - { address: '0x87647780180b8f55980c7d3ffefe08a9b29e9ae1', chain: Chain.CELO, label: 'Custody Multisig', custodianType: 'cold' }, - { address: '0xD3D2e5c5Af667DA817b2D752d86c8f40c22137E1', chain: Chain.CELO, label: 'Ops Multisig', custodianType: 'ops' }, - { address: '0x6dec25d7be9bf6c6fc302977629f2e801e98611c', chain: Chain.CELO, label: 'Operational Account', custodianType: 'ops' }, - { address: '0x13a9803d547332c81ebc6060f739821264dbcf1e', chain: Chain.CELO, label: 'Operational Account', custodianType: 'ops' }, - { address: '0x619600F4ec13C38868841cB83100F611eCF94eE8', chain: Chain.CELO, label: 'Falcon Finance', custodianType: 'cold' }, - { address: '0xaa8299fc6a685b5f9ce9bda8d0b3ea3d54731976', chain: Chain.CELO, label: 'Rebalancer Bot', custodianType: 'ops' }, - // --- Ethereum --- - { address: '0x9380fA34Fd9e4Fd14c06305fd7B6199089eD4eb9', chain: Chain.ETHEREUM, label: 'Mento Pools Liquidity Reserve', custodianType: 'hot' }, - { address: '0xd0697f70E79476195B742d5aFAb14BE50f98CC1E', chain: Chain.ETHEREUM, label: 'ETH Custody Multisig', custodianType: 'cold' }, - { address: '0xD3D2e5c5Af667DA817b2D752d86c8f40c22137E1', chain: Chain.ETHEREUM, label: 'Ops Multisig', custodianType: 'ops' }, - { address: '0xaa8299fc6a685b5f9ce9bda8d0b3ea3d54731976', chain: Chain.ETHEREUM, label: 'Rebalancer Bot', custodianType: 'ops' }, - { address: '0x6dec25d7be9bf6c6fc302977629f2e801e98611c', chain: Chain.ETHEREUM, label: 'Operational Account', custodianType: 'ops' }, - // --- Monad --- - { address: '0x4255Cf38e51516766180b33122029A88Cb853806', chain: Chain.MONAD, label: 'ReserveV2', custodianType: 'hot' }, - { address: '0x87647780180B8f55980C7D3fFeFe08a9B29e9aE1', chain: Chain.MONAD, label: 'Reserve Safe', custodianType: 'cold' }, - { address: '0x6dec25d7be9bf6c6fc302977629f2e801e98611c', chain: Chain.MONAD, label: 'Operational Account', custodianType: 'ops' }, - { address: '0x13a9803d547332c81ebc6060f739821264dbcf1e', chain: Chain.MONAD, label: 'Operational Account', custodianType: 'ops' }, + { address: '0x9380fA34Fd9e4Fd14c06305fd7B6199089eD4eb9', chains: [Chain.CELO, Chain.ETHEREUM], label: 'Mento V2 Liquidity Reserve', custodianType: 'hot', description: 'Active liquidity for stablecoin swaps in Mento V2' }, + { address: '0x4255Cf38e51516766180b33122029A88Cb853806', chains: [Chain.CELO, Chain.MONAD], label: 'Mento V3 Liquidity Reserve', custodianType: 'hot', description: 'Active liquidity for stablecoin swaps in Mento V3' }, + { address: '0x87647780180B8f55980C7D3fFeFe08a9B29e9aE1', chains: [Chain.CELO, Chain.MONAD], label: 'Reserve Safe', custodianType: 'cold', description: 'Mento Reserve Asset Custody' }, + { address: '0xd0697f70E79476195B742d5aFAb14BE50f98CC1E', chains: [Chain.ETHEREUM], label: 'Reserve Safe', custodianType: 'cold', description: 'Mento Reserve Asset Custody' }, + { address: '0xD3D2e5c5Af667DA817b2D752d86c8f40c22137E1', chains: [Chain.CELO, Chain.ETHEREUM], label: 'Ops Safe', custodianType: 'ops', description: 'Accounts used to provide liquidity to FPMMs and other protocols on behalf of the reserve' }, + { address: '0x13a9803d547332c81ebc6060f739821264dbcf1e', chains: [Chain.CELO, Chain.MONAD], label: 'Ops Account', custodianType: 'ops', description: 'Accounts used to provide liquidity to FPMMs and other protocols on behalf of the reserve' }, + { address: '0xaa8299fc6a685b5f9ce9bda8d0b3ea3d54731976', chains: [Chain.CELO, Chain.ETHEREUM], label: 'Rebalancer Bot', custodianType: 'ops', description: 'Account executing active rebalancing on behalf of the reserve' }, ]; /** Get all reserve addresses for a specific chain */ export function getReserveAddressesByChain(chain: Chain): ReserveAddress[] { - return RESERVE_ADDRESSES.filter((a) => a.chain === chain); + return RESERVE_ADDRESSES.filter((a) => a.chains.includes(chain)); } /** Check if an address is a reserve address (case-insensitive) on any chain */ diff --git a/src/api/v2/controllers/v2-addresses.controller.ts b/src/api/v2/controllers/v2-addresses.controller.ts index d527656..ded6f08 100644 --- a/src/api/v2/controllers/v2-addresses.controller.ts +++ b/src/api/v2/controllers/v2-addresses.controller.ts @@ -14,7 +14,7 @@ export class V2AddressesController { ) {} @Get() - @ApiOperation({ summary: 'Get reserve addresses grouped by network and category' }) + @ApiOperation({ summary: 'Get reserve addresses with chain and custodian metadata' }) @ApiResponse({ status: 200, type: V2AddressesResponseDto }) async getAddresses(): Promise { return this.cacheWarmerService.getOrRevalidate(V2_CACHE_KEYS.ADDRESSES, () => diff --git a/src/api/v2/dto/v2-addresses.dto.ts b/src/api/v2/dto/v2-addresses.dto.ts index 679a9f1..6aab889 100644 --- a/src/api/v2/dto/v2-addresses.dto.ts +++ b/src/api/v2/dto/v2-addresses.dto.ts @@ -3,21 +3,12 @@ import { Chain } from '@types'; export class V2AddressDto { @ApiProperty() address: string; + @ApiProperty({ enum: Chain, isArray: true }) chains: Chain[]; @ApiProperty() label: string; - @ApiProperty({ enum: ['hot', 'cold', 'ops'], required: false }) custodian_type?: string; + @ApiProperty({ enum: ['hot', 'cold', 'ops'] }) custodian_type: string; @ApiProperty({ required: false }) description?: string; } -export class V2AddressCategoryDto { - @ApiProperty() category: string; - @ApiProperty({ type: [V2AddressDto] }) addresses: V2AddressDto[]; -} - -export class V2NetworkAddressesDto { - @ApiProperty({ enum: Chain }) chain: Chain; - @ApiProperty({ type: [V2AddressCategoryDto] }) categories: V2AddressCategoryDto[]; -} - export class V2AddressesResponseDto { - @ApiProperty({ type: [V2NetworkAddressesDto] }) networks: V2NetworkAddressesDto[]; + @ApiProperty({ type: [V2AddressDto] }) reserve: V2AddressDto[]; } diff --git a/src/api/v2/services/v2-addresses.service.ts b/src/api/v2/services/v2-addresses.service.ts index 4ec040c..7701c32 100644 --- a/src/api/v2/services/v2-addresses.service.ts +++ b/src/api/v2/services/v2-addresses.service.ts @@ -1,71 +1,18 @@ import { Injectable } from '@nestjs/common'; -import { getReserveAddressesByChain } from '../config/reserve-addresses.config'; -import { CDP_TROVE_CONFIGS, CDP_REGISTRIES } from '../config/cdp.config'; -import { V2AddressesResponseDto, V2NetworkAddressesDto, V2AddressCategoryDto } from '../dto/v2-addresses.dto'; -import { Chain } from '@types'; +import { RESERVE_ADDRESSES } from '../config/reserve-addresses.config'; +import { V2AddressesResponseDto } from '../dto/v2-addresses.dto'; @Injectable() export class V2AddressesService { getAddresses(): V2AddressesResponseDto { - const networkMap = new Map>(); - const chainOrder = [Chain.CELO, Chain.ETHEREUM, Chain.MONAD]; - - for (const chain of chainOrder) { - const addresses = getReserveAddressesByChain(chain); - if (addresses.length === 0) continue; - - const categoryMap = new Map(); - const categoryKey = 'Mento Reserve'; - categoryMap.set(categoryKey, { category: categoryKey, addresses: [] }); - - const group = categoryMap.get(categoryKey)!; - for (const addr of addresses) { - if (!group.addresses.some((a) => a.address.toLowerCase() === addr.address.toLowerCase())) { - group.addresses.push({ - address: addr.address, - label: addr.label, - custodian_type: addr.custodianType, - }); - } - } - - networkMap.set(chain, categoryMap); - } - - // Add CDP contract addresses - for (const cdp of CDP_TROVE_CONFIGS) { - if (cdp.status !== 'active') continue; - - const contractAddress = cdp.contractAddress || CDP_REGISTRIES[cdp.stablecoin]; - if (!contractAddress) continue; - - if (!networkMap.has(cdp.chain)) { - networkMap.set(cdp.chain, new Map()); - } - - const categoryMap = networkMap.get(cdp.chain)!; - const categoryKey = 'CDP Contract'; - - if (!categoryMap.has(categoryKey)) { - categoryMap.set(categoryKey, { category: categoryKey, addresses: [] }); - } - - const label = cdp.contractAddress ? `${cdp.stablecoin} TroveManager` : `${cdp.stablecoin} AddressesRegistry`; - - categoryMap.get(categoryKey)!.addresses.push({ - address: contractAddress, - label, - description: `CDP system for minting ${cdp.stablecoin} with ${cdp.collateralToken} collateral`, - }); - } - - const networks: V2NetworkAddressesDto[] = chainOrder - .filter((c) => networkMap.has(c)) - .map((chain) => ({ - chain, - categories: Array.from(networkMap.get(chain)!.values()), - })); - - return { networks }; + return { + reserve: RESERVE_ADDRESSES.map((addr) => ({ + address: addr.address, + chains: addr.chains, + label: addr.label, + custodian_type: addr.custodianType, + description: addr.description, + })), + }; } }