Skip to content

Commit 10d0bd7

Browse files
Jwhilesclaude
andcommitted
feat(money-account-upgrade-controller): persist upgrade status and add retry
Track fully upgraded accounts in persisted controller state, keyed by lowercased address and fingerprinted against the active upgrade config, so upgradeAccount skips the step sequence once an account is recorded as upgraded and re-runs it when the config changes. Add upgradeAccountWithRetry, retrying failed attempts with capped exponential backoff (10s/20s/40s/60s, 5 attempts by default) and AbortSignal cancellation. Failures that cannot resolve by retrying (account delegated to a third-party EIP-7702 implementation, or unexpected on-chain code) are marked terminal via TerminalUpgradeError and are not retried. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 621fbe4 commit 10d0bd7

9 files changed

Lines changed: 819 additions & 13 deletions

packages/money-account-upgrade-controller/CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Add persisted state tracking fully upgraded accounts ([#9999](https://github.com/MetaMask/core/pull/9999))
13+
- `MoneyAccountUpgradeControllerState` now contains `upgradedAccounts`, keyed by lowercased account address. Each entry records when the upgrade sequence completed and a fingerprint of the config it completed under (see new `MoneyAccountUpgradeStatus` type).
14+
- The constructor now accepts an optional `state` option, merged with the defaults; add `getDefaultMoneyAccountUpgradeControllerState` to construct those defaults.
15+
- Add `upgradeAccountWithRetry` method and matching `MoneyAccountUpgradeController:upgradeAccountWithRetry` messenger action ([#9999](https://github.com/MetaMask/core/pull/9999))
16+
- Retries failed `upgradeAccount` attempts with capped exponential backoff (10s, 20s, 40s, then 60s between attempts; 5 attempts by default). Terminal failures and non-step errors are rethrown without retrying. Accepts an `AbortSignal` to cancel waiting between attempts.
17+
- Add `TerminalUpgradeError` and `isTerminalMoneyAccountUpgradeError`, and a `terminal` property on `MoneyAccountUpgradeStepError`, marking failures that cannot resolve by retrying — currently an account delegated to a third-party EIP-7702 implementation, or an account with unexpected on-chain code ([#9999](https://github.com/MetaMask/core/pull/9999))
18+
1019
### Changed
1120

21+
- `upgradeAccount` now skips the step sequence entirely when the account is recorded in state as upgraded under the active config fingerprint, and records the account after a successful run. If the chain, CHOMP contract addresses, or Delegation Framework version change, the fingerprint no longer matches and the sequence re-runs ([#9999](https://github.com/MetaMask/core/pull/9999))
1222
- Bump `@metamask/messenger` from `^1.2.0` to `^2.0.0` ([#9392](https://github.com/MetaMask/core/pull/9392))
1323
- Bump `@metamask/authenticated-user-storage` from `^3.0.0` to `^3.0.1` ([#9458](https://github.com/MetaMask/core/pull/9458))
1424

packages/money-account-upgrade-controller/src/MoneyAccountUpgradeController-method-action-types.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,43 @@ import type { MoneyAccountUpgradeController } from './MoneyAccountUpgradeControl
1313
* {@link MoneyAccountUpgradeStepError} that records which step failed (the
1414
* original error is preserved as `cause`).
1515
*
16+
* A run that completes is recorded in state (keyed by lowercased address,
17+
* fingerprinted against the active config); subsequent calls for a
18+
* recorded account return immediately without running any steps. If the
19+
* active config no longer matches the recorded fingerprint, the sequence
20+
* re-runs.
21+
*
1622
* @param address - The Money Account address to upgrade.
1723
*/
1824
export type MoneyAccountUpgradeControllerUpgradeAccountAction = {
1925
type: `MoneyAccountUpgradeController:upgradeAccount`;
2026
handler: MoneyAccountUpgradeController['upgradeAccount'];
2127
};
2228

29+
/**
30+
* Runs the upgrade sequence via
31+
* {@link MoneyAccountUpgradeController.upgradeAccount}, retrying failed
32+
* attempts with capped exponential backoff (10s, 20s, 40s, then 60s
33+
* between attempts). Rethrows the last error without further attempts when
34+
* the failure is terminal (see `isTerminalMoneyAccountUpgradeError`), when
35+
* it is not a step failure at all, or when `maxAttempts` is exhausted.
36+
*
37+
* @param address - The Money Account address to upgrade.
38+
* @param options - Retry options.
39+
* @param options.signal - Aborts waiting between attempts and prevents
40+
* further attempts. An aborted run rejects with an error stating the retry
41+
* was aborted.
42+
* @param options.maxAttempts - Maximum number of attempts, including the
43+
* first. Defaults to 5.
44+
*/
45+
export type MoneyAccountUpgradeControllerUpgradeAccountWithRetryAction = {
46+
type: `MoneyAccountUpgradeController:upgradeAccountWithRetry`;
47+
handler: MoneyAccountUpgradeController['upgradeAccountWithRetry'];
48+
};
49+
2350
/**
2451
* Union of all MoneyAccountUpgradeController action types.
2552
*/
2653
export type MoneyAccountUpgradeControllerMethodActions =
27-
MoneyAccountUpgradeControllerUpgradeAccountAction;
54+
| MoneyAccountUpgradeControllerUpgradeAccountAction
55+
| MoneyAccountUpgradeControllerUpgradeAccountWithRetryAction;

0 commit comments

Comments
 (0)