Skip to content

Commit 24d7d65

Browse files
committed
feat: made all VaultApyResponse fields optional except for apy and timestamp. Vaults aren't guaranteed to have the other properties when there's no activity
1 parent aa31fa3 commit 24d7d65

4 files changed

Lines changed: 57 additions & 37 deletions

File tree

packages/money-account-controller/src/money-account-balance-service/requestNormalization.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Infer } from '@metamask/superstruct';
22

3-
import { VaultApyResponseStruct } from './structs';
43
import { VaultApyResponse } from './response.types';
4+
import { VaultApyResponseStruct } from './structs';
55

66
/**
77
* Normalizes the raw response from the Veda performance API into the expected
@@ -20,13 +20,15 @@ export function normalizeVaultApyResponse(
2020
apy: response.apy,
2121
chainAllocation: response.chain_allocation,
2222
fees: response.fees,
23-
globalApyBreakdown: {
24-
fee: response.global_apy_breakdown.fee,
25-
maturityApy: response.global_apy_breakdown.maturity_apy,
26-
realApy: response.global_apy_breakdown.real_apy,
27-
},
23+
globalApyBreakdown: response.global_apy_breakdown
24+
? {
25+
fee: response.global_apy_breakdown.fee,
26+
maturityApy: response.global_apy_breakdown.maturity_apy,
27+
realApy: response.global_apy_breakdown.real_apy,
28+
}
29+
: undefined,
2830
performanceFees: response.performance_fees,
29-
realApyBreakdown: response.real_apy_breakdown.map((item) => ({
31+
realApyBreakdown: response.real_apy_breakdown?.map((item) => ({
3032
allocation: item.allocation,
3133
apy: item.apy,
3234
apyNet: item.apy_net,

packages/money-account-controller/src/money-account-balance-service/response.types.ts

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,26 +28,29 @@ export type MusdEquivalentValueResponse = {
2828
/**
2929
* Response from {@link MoneyAccountBalanceService.getVaultApy}.
3030
* All APY / fee values are decimals (multiply by 100 for percentage).
31+
*
32+
* Only `apy` and `timestamp` are guaranteed to be present — all other fields
33+
* are optional because the Veda API omits them when the vault has no activity.
3134
*/
3235
export type VaultApyResponse = {
33-
aggregationPeriod: string; // E.g. "7 days"
36+
aggregationPeriod?: string; // E.g. "7 days"
3437
apy: number;
35-
chainAllocation: {
38+
chainAllocation?: {
3639
[network: string]: number;
3740
};
38-
fees: number;
39-
globalApyBreakdown: {
40-
fee: number;
41-
maturityApy: number;
42-
realApy: number;
41+
fees?: number;
42+
globalApyBreakdown?: {
43+
fee?: number;
44+
maturityApy?: number;
45+
realApy?: number;
4346
};
44-
performanceFees: number;
45-
realApyBreakdown: {
46-
allocation: number;
47-
apy: number;
48-
apyNet: number;
49-
chain: string;
50-
protocol: string;
47+
performanceFees?: number;
48+
realApyBreakdown?: {
49+
allocation?: number;
50+
apy?: number;
51+
apyNet?: number;
52+
chain?: string;
53+
protocol?: string;
5154
}[];
5255
timestamp: string;
5356
};
Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,46 @@
1-
import { array, number, record, string, type } from '@metamask/superstruct';
1+
import {
2+
array,
3+
number,
4+
optional,
5+
record,
6+
string,
7+
type,
8+
} from '@metamask/superstruct';
29

310
/**
411
* Superstruct schema for {@link VaultApyResponse}.
512
*
613
* Uses `type()` (loose validation) so that unknown fields returned by the
714
* Veda API do not cause validation failures.
15+
*
16+
* Only `apy` and `timestamp` are required — all other fields are optional
17+
* because the Veda API omits some fields when the vault has no activity.
818
*/
919
export const VaultApyResponseStruct = type({
1020
Response: type({
11-
aggregation_period: string(),
21+
aggregation_period: optional(string()),
1222
apy: number(),
13-
chain_allocation: record(string(), number()),
14-
fees: number(),
15-
global_apy_breakdown: type({
16-
fee: number(),
17-
maturity_apy: number(),
18-
real_apy: number(),
19-
}),
20-
performance_fees: number(),
21-
real_apy_breakdown: array(
23+
chain_allocation: optional(record(string(), number())),
24+
fees: optional(number()),
25+
global_apy_breakdown: optional(
2226
type({
23-
allocation: number(),
24-
apy: number(),
25-
apy_net: number(),
26-
chain: string(),
27-
protocol: string(),
27+
fee: optional(number()),
28+
maturity_apy: optional(number()),
29+
real_apy: optional(number()),
2830
}),
2931
),
32+
performance_fees: optional(number()),
33+
real_apy_breakdown: optional(
34+
array(
35+
type({
36+
allocation: optional(number()),
37+
apy: optional(number()),
38+
apy_net: optional(number()),
39+
chain: optional(string()),
40+
protocol: optional(string()),
41+
}),
42+
),
43+
),
3044
timestamp: string(),
3145
}),
3246
});

yarn.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4427,6 +4427,7 @@ __metadata:
44274427
async-mutex: "npm:^0.5.0"
44284428
deepmerge: "npm:^4.2.2"
44294429
jest: "npm:^29.7.0"
4430+
nock: "npm:^13.3.1"
44304431
ts-jest: "npm:^29.2.5"
44314432
tsx: "npm:^4.20.5"
44324433
typedoc: "npm:^0.25.13"

0 commit comments

Comments
 (0)