Skip to content

Commit 1967e88

Browse files
committed
feat: enhance vault handling and status responses with improved key mapping and withdrawal support
1 parent 9c91b6f commit 1967e88

5 files changed

Lines changed: 43 additions & 19 deletions

File tree

apps/api/src/config/vault-registry.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { cmsService } from "../services/cms.service";
22
import { pool } from "../db/postgres";
3-
import { IAtvVault } from "../types/vault.types";
3+
import { DepositContractType, IAtvVault } from "../types/vault.types";
44

55
/**
66
* Vault registry — the single source of truth for vault configs across this service.
@@ -27,12 +27,22 @@ class VaultRegistry {
2727
}
2828

2929
/**
30-
* Returns a map of lowercase atvTokenAddress → IAtvVault for O(1) lookup.
30+
* Returns a map of lookup address → IAtvVault for O(1) lookup.
31+
*
32+
* For ERC4626 vaults the user-facing address is the timelock contract,
33+
* so we key by timelock address. All other vaults key by atvTokenAddress.
3134
*/
3235
async getVaultMap(): Promise<Record<string, IAtvVault>> {
3336
const vaults = await this.getVaults();
3437
return Object.fromEntries(
35-
vaults.map((v) => [v.atvTokenAddress.toLowerCase(), v]),
38+
vaults.map((v) => {
39+
const key =
40+
v.depositContractType === DepositContractType.ERC4626 &&
41+
v.contracts.timelock?.address
42+
? v.contracts.timelock.address.toLowerCase()
43+
: v.atvTokenAddress.toLowerCase();
44+
return [key, v];
45+
}),
3646
);
3747
}
3848

apps/api/src/handlers/vaults.handler.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,10 @@ export const vaultsHandler = {
102102
) => {
103103
try {
104104
const data = await vaultService.getQueueWithdrawStatus(req.params.address);
105-
res.json({ data, message: 'Queue withdraw status retrieved', statusCode: 200 });
105+
const message = data.supported
106+
? 'Queue withdraw status retrieved'
107+
: 'Queue withdraw method not supported for this vault';
108+
res.json({ data, message, statusCode: 200 });
106109
} catch (err) {
107110
next(err);
108111
}

apps/api/src/services/cms.service.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,9 @@ class CmsService {
6060
}
6161

6262
async getVaults(): Promise<IAtvVault[]> {
63-
// if (this.isCacheValid) {
64-
// return this.cache!.vaults;
65-
// }
63+
if (this.isCacheValid) {
64+
return this.cache!.vaults;
65+
}
6666

6767
const vaults = await this.fetchFromCms();
6868
this.cache = { vaults, fetchedAt: Date.now() };
@@ -164,9 +164,7 @@ class CmsService {
164164
(item.depositContractType?.toUpperCase() as DepositContractType) ??
165165
DepositContractType.ERC20,
166166
withdrawType: item.withdrawType?.length
167-
? (item.withdrawType.map((w) =>
168-
w.toUpperCase(),
169-
) as WithdrawType[])
167+
? (item.withdrawType.map((w) => w.toUpperCase()) as WithdrawType[])
170168
: [WithdrawType.INSTANT],
171169
depositFee: item.depositFee,
172170
contracts: {

apps/api/src/services/vault.service.ts

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
VaultMetadata,
1515
VaultStatusResponse,
1616
} from "../types/api.types";
17-
import { IAtvVault } from "../types/vault.types";
17+
import { IAtvVault, WithdrawType } from "../types/vault.types";
1818

1919
export class VaultService {
2020
private toMetadata(
@@ -157,7 +157,7 @@ export class VaultService {
157157
} catch (e: any) {
158158
console.error(
159159
`[VaultService] getDepositTokens failed for vault ${vault.productId} ` +
160-
`(atvTokenAddress=${vault.atvTokenAddress}, chainId=${vault.chain.decimal}):`,
160+
`(atvTokenAddress=${vault.atvTokenAddress}, chainId=${vault.chain.decimal}):`,
161161
e,
162162
);
163163
return [];
@@ -288,9 +288,9 @@ export class VaultService {
288288
[],
289289
vault.chain,
290290
);
291-
return { vaultAddress: vault.atvTokenAddress, isPaused, supported: true };
291+
return { isPaused, supported: true };
292292
} catch {
293-
return { vaultAddress: vault.atvTokenAddress, isPaused: false, supported: false };
293+
return { isPaused: false, supported: false };
294294
}
295295
}
296296

@@ -304,14 +304,28 @@ export class VaultService {
304304
[],
305305
vault.chain,
306306
);
307-
return { vaultAddress: vault.atvTokenAddress, isPaused, supported: true };
307+
return { isPaused, supported: true };
308308
} catch {
309-
return { vaultAddress: vault.atvTokenAddress, isPaused: false, supported: false };
309+
return { isPaused: false, supported: false };
310310
}
311311
}
312312

313+
private static QUEUE_WITHDRAW_TYPES = new Set<WithdrawType>([
314+
WithdrawType.STANDARD,
315+
WithdrawType.STANDARD_AUTO_REDEEM,
316+
]);
317+
313318
async getQueueWithdrawStatus(address: string): Promise<VaultStatusResponse> {
314319
const vault = await vaultRegistry.getVaultOrThrow(address);
320+
321+
// Check if the vault supports queued withdrawals based on CMS config
322+
const supportsQueue = vault.withdrawType.some((t) =>
323+
VaultService.QUEUE_WITHDRAW_TYPES.has(t),
324+
);
325+
if (!supportsQueue) {
326+
return { isPaused: false, supported: false };
327+
}
328+
315329
try {
316330
const isPaused = await ethersHelper.readContract<boolean>(
317331
vault.contracts.base.address,
@@ -320,9 +334,9 @@ export class VaultService {
320334
[],
321335
vault.chain,
322336
);
323-
return { vaultAddress: vault.atvTokenAddress, isPaused, supported: true };
337+
return { isPaused, supported: true };
324338
} catch {
325-
return { vaultAddress: vault.atvTokenAddress, isPaused: false, supported: false };
339+
return { isPaused: false, supported: false };
326340
}
327341
}
328342
}

apps/api/src/types/api.types.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ export interface ApyResponse {
7171
}
7272

7373
export interface VaultStatusResponse {
74-
vaultAddress: string;
7574
isPaused: boolean;
7675
supported: boolean; // false when contract doesn't expose the status function
7776
}

0 commit comments

Comments
 (0)