Skip to content

feat(money): update response structs for money account api data service - #10500

Merged
ffmcgee725 merged 2 commits into
mainfrom
jc/money-account-api-data-service-update-validaction-structs
Sep 28, 2026
Merged

ffmcgee725 merged 2 commits into
mainfrom
jc/money-account-api-data-service-update-validaction-structs

Conversation

@ffmcgee725

@ffmcgee725 ffmcgee725 commented Sep 28, 2026 •

Copy link
Copy Markdown
Member

Explanation

  • @metamask/money-account-api-data-service: fetchPositions now validates the current Money Account API positions contract.
    • Each vault position includes chain_id, vault_key, name, asset_symbol, and asset_decimals.
    • The balance summary includes by_asset and total_balance_usd. AssetBalance is exported. The legacy mUSD fields (musd_balance, vmusd_value_in_musd, total_balance) remain and still cover mUSD-denominated holdings only.
    • Breaking: effective_apy is string | null. null means the position has been invested for fewer than 28 days, and is distinct from a rate of zero.
  • Responses that omit the new required fields fail validation. Interest, history, and rate-history responses are unchanged.

Test plan

  • money-account-api-data-service unit tests (positions fixture includes vault metadata and by_asset; effective_apy: null is accepted)
  • Changelog validation for @metamask/money-account-api-data-service

Note

Medium Risk
Breaking TypeScript contract and stricter response validation for positions; downstream callers must handle nullable effective_apy and new required API fields or face validation failures at runtime.

Overview
Updates @metamask/money-account-api-data-service so fetchPositions validates the current Money Account API positions payload, not the older mUSD-only shape.

Each vault position now requires metadata: chain_id, vault_key, name, asset_symbol, and asset_decimals. The balance summary adds multi-asset by_asset (with new exported AssetBalance type) and total_balance_usd; legacy mUSD fields remain for mUSD-only totals.

Breaking: effective_apy is string | null — null means fewer than 28 days invested (not a zero rate). Superstruct validation and TypeScript types stay in sync; responses missing the new required fields still throw MoneyAccountApiResponseValidationError. Interest, history, and rate-history endpoints are unchanged.

Reviewed by Cursor Bugbot for commit a757e78. Bugbot is set up for automated code reviews on this repo. Configure here.

@ffmcgee725
ffmcgee725 marked this pull request as ready for review September 28, 2026 09:16
@ffmcgee725
ffmcgee725 requested review from a team as code owners September 28, 2026 09:16
@ffmcgee725
ffmcgee725 added this pull request to the merge queue Sep 28, 2026
Merged via the queue into main with commit 9d62119 Sep 28, 2026
60 checks passed
@ffmcgee725
ffmcgee725 deleted the jc/money-account-api-data-service-update-validaction-structs branch September 28, 2026 09:38
@ffmcgee725 ffmcgee725 mentioned this pull request Sep 28, 2026
FrederikBolding pushed a commit that referenced this pull request Sep 28, 2026
…ce (#10500)

## Explanation

- `@metamask/money-account-api-data-service`: `fetchPositions` now
validates the current Money Account API positions contract.
- Each vault position includes `chain_id`, `vault_key`, `name`,
`asset_symbol`, and `asset_decimals`.
- The `balance` summary includes `by_asset` and `total_balance_usd`.
`AssetBalance` is exported. The legacy mUSD fields (`musd_balance`,
`vmusd_value_in_musd`, `total_balance`) remain and still cover
mUSD-denominated holdings only.
- **Breaking:** `effective_apy` is `string | null`. `null` means the
position has been invested for fewer than 28 days, and is distinct from
a rate of zero.
- Responses that omit the new required fields fail validation. Interest,
history, and rate-history responses are unchanged.

## Test plan

- [x] `money-account-api-data-service` unit tests (positions fixture
includes vault metadata and `by_asset`; `effective_apy: null` is
accepted)
- [x] Changelog validation for
`@metamask/money-account-api-data-service`

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Breaking TypeScript contract and stricter response validation for
positions; downstream callers must handle nullable `effective_apy` and
new required API fields or face validation failures at runtime.
> 
> **Overview**
> Updates `@metamask/money-account-api-data-service` so
**`fetchPositions`** validates the current Money Account API positions
payload, not the older mUSD-only shape.
> 
> Each **vault position** now requires metadata: `chain_id`,
`vault_key`, `name`, `asset_symbol`, and `asset_decimals`. The
**`balance`** summary adds multi-asset **`by_asset`** (with new exported
**`AssetBalance`** type) and **`total_balance_usd`**; legacy mUSD fields
remain for mUSD-only totals.
> 
> **Breaking:** **`effective_apy`** is **`string | null`** — `null`
means fewer than 28 days invested (not a zero rate). Superstruct
validation and TypeScript types stay in sync; responses missing the new
required fields still throw
**`MoneyAccountApiResponseValidationError`**. Interest, history, and
rate-history endpoints are unchanged.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
a757e78. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
FrederikBolding pushed a commit that referenced this pull request Sep 28, 2026
## @metamask/base-data-service

## [2.1.0]

### Added

- Add `executeMutation` protected method to `BaseDataService` to allow
for making server-state-mutating requests
([#9324](#9324))
  - These kinds of requests are never retried, unlike queries.
- To use this, create a method in your data service class which takes
whatever arguments you need, plus a optional final argument called
`globalId`; then call `executeMutation` with a `mutationKey`,
`globalId`, and `mutationFn`. See `ExampleDataService` in this package
for an example.
  - A `MutationKey` type is also available.
- Add protected `cancelQueries` so subclasses can abort in-flight reads
before a forced refresh
([#10454](#10454))

### Changed

- The payload for `:cacheUpdated` and `:cacheUpdated:${hash}` events now
includes an `objectType` property, which is either "query" or "mutation"
([#9324](#9324))
- Bump `@metamask/utils` from `^11.12.0` to `^12.0.0`
([#10192](#10192))
- Add `uuid` `^11.1.1` as a dependency
([#9324](#9324))
- Bump `@tanstack/query-core` from `^5.62.16` to `^5.89.0`
([#9324](#9324))
- Bump `cockatiel` from `^3.1.2` to `^3.2.1`
([#10436](#10436))
- Bump `lodash-es` from `^4.17.21` to `^4.18.1`
([#10447](#10447))

## @metamask/money-account-api-data-service

## [2.0.0]

### Added

- Add optional `fresh` option to `fetchPositions` that cancels in-flight
reads, fetches with a zero stale time, invalidates the result for
subsequent reads, and sends `Cache-Control: no-cache` so the Money API
skips its Nest response cache when supported
([#10455](#10455))
- Accept optional additive `musd_balance_updated_at` on the positions
`balance` summary
([#10455](#10455))
- Accept vault metadata on each position returned by `fetchPositions`:
`chain_id`, `vault_key`, `name`, `asset_symbol`, and `asset_decimals`
([#10500](#10500))
- Accept multi-asset balance fields `by_asset` and `total_balance_usd`
on the positions `balance` summary, and export `AssetBalance`
([#10500](#10500))

### Changed

- **BREAKING:** `effective_apy` on a vault position is now `string |
null`. `null` means the position has been invested for fewer than 28
days, and is distinct from a rate of zero
([#10500](#10500))
- Bump `@metamask/base-data-service` from `^2.0.0` to `^2.1.0`
- Bump `@metamask/utils` from `^11.12.0` to `^12.0.0`
([#10192](#10192))
- Bump `@tanstack/query-core` from `^5.62.16` to `^5.89.0`
([#9324](#9324))

## @metamask/money-account-balance-service

## [3.1.0]

### Added

- Surface Money API freshness on `fetchBalanceWithFallback` results
(`asOfBlock`, `asOfTimestamp`, `dataFreshness`, `indexerLagSeconds`,
`musdBalanceUpdatedAt`) when `source` is `api`
([#10455](#10455))
- Add optional `FetchBalanceWithFallbackOptions` (`minBlock`, `fresh`):
when the API `as_of_block` is behind `minBlock`, throw
`MoneyAccountBalanceStaleError` and fall back to RPC without reporting a
defect; `minBlock` implies a fresh positions read, and explicit `fresh`
is also forwarded to `fetchPositions`
([#10455](#10455))
- Export `MoneyAccountBalanceStaleError`
([#10455](#10455))

### Changed

- Bump `@metamask/money-account-api-data-service` from `^1.0.0` to
`^2.0.0`
- Bump `@metamask/base-data-service` from `^2.0.0` to `^2.1.0`
- Bump `@metamask/utils` from `^11.12.0` to `^12.0.0`
([#10192](#10192))
- Bump `@ethersproject/providers` from `^5.7.0` to `^5.8.0`
([#10482](#10482))

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> The release bundles Money balance/positions API behavior changes
including a breaking type change and post-tx staleness fallback logic,
even though this PR only cuts versions and dependency ranges.
> 
> **Overview**
> **Monorepo release 1294.0.0** that cuts new package versions and
aligns dependents—there are no application source edits in this diff,
only `package.json`, changelog, and lockfile updates.
> 
> **Version cuts:** `@metamask/base-data-service` **2.1.0**,
`@metamask/money-account-api-data-service` **2.0.0**, and
`@metamask/money-account-balance-service` **3.1.0**, with `[Unreleased]`
notes moved into those release sections. The root monorepo version moves
**1293.0.0 → 1294.0.0**.
> 
> **Dependency propagation:** Every listed consumer bumps
`@metamask/base-data-service` from `^2.0.0` to `^2.1.0`.
`@metamask/money-account-balance-service` picks up
`@metamask/money-account-api-data-service` **^2.0.0**;
`@metamask/subscription-controller` also bumps
`@metamask/money-account-balance-service` to **^3.1.0**.
> 
> **What ships in those releases (via changelog, not new code here):**
`BaseDataService` gains mutation/query-cancel plumbing and richer cache
events; Money API positions support forced refresh, richer
balance/position shapes, and a **breaking** `effective_apy: string |
null`; balance fallback exposes API freshness metadata and optional
`minBlock` / `fresh` behavior with `MoneyAccountBalanceStaleError`.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
ee833b1. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
pull Bot pushed a commit to Reality2byte/core that referenced this pull request Sep 28, 2026
## @metamask/base-data-service

## [2.1.0]

### Added

- Add `executeMutation` protected method to `BaseDataService` to allow
for making server-state-mutating requests
([MetaMask#9324](MetaMask#9324))
  - These kinds of requests are never retried, unlike queries.
- To use this, create a method in your data service class which takes
whatever arguments you need, plus a optional final argument called
`globalId`; then call `executeMutation` with a `mutationKey`,
`globalId`, and `mutationFn`. See `ExampleDataService` in this package
for an example.
  - A `MutationKey` type is also available.
- Add protected `cancelQueries` so subclasses can abort in-flight reads
before a forced refresh
([MetaMask#10454](MetaMask#10454))

### Changed

- The payload for `:cacheUpdated` and `:cacheUpdated:${hash}` events now
includes an `objectType` property, which is either "query" or "mutation"
([MetaMask#9324](MetaMask#9324))
- Bump `@metamask/utils` from `^11.12.0` to `^12.0.0`
([MetaMask#10192](MetaMask#10192))
- Add `uuid` `^11.1.1` as a dependency
([MetaMask#9324](MetaMask#9324))
- Bump `@tanstack/query-core` from `^5.62.16` to `^5.89.0`
([MetaMask#9324](MetaMask#9324))
- Bump `cockatiel` from `^3.1.2` to `^3.2.1`
([MetaMask#10436](MetaMask#10436))
- Bump `lodash-es` from `^4.17.21` to `^4.18.1`
([MetaMask#10447](MetaMask#10447))

## @metamask/money-account-api-data-service

## [2.0.0]

### Added

- Add optional `fresh` option to `fetchPositions` that cancels in-flight
reads, fetches with a zero stale time, invalidates the result for
subsequent reads, and sends `Cache-Control: no-cache` so the Money API
skips its Nest response cache when supported
([MetaMask#10455](MetaMask#10455))
- Accept optional additive `musd_balance_updated_at` on the positions
`balance` summary
([MetaMask#10455](MetaMask#10455))
- Accept vault metadata on each position returned by `fetchPositions`:
`chain_id`, `vault_key`, `name`, `asset_symbol`, and `asset_decimals`
([MetaMask#10500](MetaMask#10500))
- Accept multi-asset balance fields `by_asset` and `total_balance_usd`
on the positions `balance` summary, and export `AssetBalance`
([MetaMask#10500](MetaMask#10500))

### Changed

- **BREAKING:** `effective_apy` on a vault position is now `string |
null`. `null` means the position has been invested for fewer than 28
days, and is distinct from a rate of zero
([MetaMask#10500](MetaMask#10500))
- Bump `@metamask/base-data-service` from `^2.0.0` to `^2.1.0`
- Bump `@metamask/utils` from `^11.12.0` to `^12.0.0`
([MetaMask#10192](MetaMask#10192))
- Bump `@tanstack/query-core` from `^5.62.16` to `^5.89.0`
([MetaMask#9324](MetaMask#9324))

## @metamask/money-account-balance-service

## [3.1.0]

### Added

- Surface Money API freshness on `fetchBalanceWithFallback` results
(`asOfBlock`, `asOfTimestamp`, `dataFreshness`, `indexerLagSeconds`,
`musdBalanceUpdatedAt`) when `source` is `api`
([MetaMask#10455](MetaMask#10455))
- Add optional `FetchBalanceWithFallbackOptions` (`minBlock`, `fresh`):
when the API `as_of_block` is behind `minBlock`, throw
`MoneyAccountBalanceStaleError` and fall back to RPC without reporting a
defect; `minBlock` implies a fresh positions read, and explicit `fresh`
is also forwarded to `fetchPositions`
([MetaMask#10455](MetaMask#10455))
- Export `MoneyAccountBalanceStaleError`
([MetaMask#10455](MetaMask#10455))

### Changed

- Bump `@metamask/money-account-api-data-service` from `^1.0.0` to
`^2.0.0`
- Bump `@metamask/base-data-service` from `^2.0.0` to `^2.1.0`
- Bump `@metamask/utils` from `^11.12.0` to `^12.0.0`
([MetaMask#10192](MetaMask#10192))
- Bump `@ethersproject/providers` from `^5.7.0` to `^5.8.0`
([MetaMask#10482](MetaMask#10482))

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> The release bundles Money balance/positions API behavior changes
including a breaking type change and post-tx staleness fallback logic,
even though this PR only cuts versions and dependency ranges.
> 
> **Overview**
> **Monorepo release 1294.0.0** that cuts new package versions and
aligns dependents—there are no application source edits in this diff,
only `package.json`, changelog, and lockfile updates.
> 
> **Version cuts:** `@metamask/base-data-service` **2.1.0**,
`@metamask/money-account-api-data-service` **2.0.0**, and
`@metamask/money-account-balance-service` **3.1.0**, with `[Unreleased]`
notes moved into those release sections. The root monorepo version moves
**1293.0.0 → 1294.0.0**.
> 
> **Dependency propagation:** Every listed consumer bumps
`@metamask/base-data-service` from `^2.0.0` to `^2.1.0`.
`@metamask/money-account-balance-service` picks up
`@metamask/money-account-api-data-service` **^2.0.0**;
`@metamask/subscription-controller` also bumps
`@metamask/money-account-balance-service` to **^3.1.0**.
> 
> **What ships in those releases (via changelog, not new code here):**
`BaseDataService` gains mutation/query-cancel plumbing and richer cache
events; Money API positions support forced refresh, richer
balance/position shapes, and a **breaking** `effective_apy: string |
null`; balance fallback exposes API freshness metadata and optional
`minBlock` / `fresh` behavior with `MoneyAccountBalanceStaleError`.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
ee833b1. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants