Reset Wallet
Archive the current wallet and spawn the next-generation copy.
Behaviour (spec §8):
- Old wallet: status=ARCHIVED, archived_at=NOW(); LedgerEntry(RESET)
emitted on the user’s accounts row as a forensic boundary marker
(reference_id=
wallet:{old_id}:reset). - New wallet: same kind, generation=N+1, parent_wallet_id=old_id,
balance=baseline (from FEATURE_MATRIX), status=ACTIVE; LedgerEntry
(DEPOSIT, baseline) emitted with reference_id=
wallet:{new_id}:init.
First-PR scope: SANDBOX only. MAIN reset uses the existing /reset-account flow (cooldown-gated, with full account_reset_backups snapshot) — that path is out of scope here. API reset uses /v1/account/reset-api-balance. COMPETITION is runner-only.
No emergency-exit step is needed yet: SANDBOX wallets do not own positions until the per-wallet routing PR. Once that lands, this endpoint must close open SANDBOX positions before archiving.
D1 — wrap in the per-user advisory lock so a concurrent SANDBOX
reset + place-trade for the same user serialize at the application
layer instead of contending on the wallets/accounts FOR UPDATE.
Reset emits LedgerEntry rows against user.account.id and
spawns a fresh wallet row; holding the lock across the body
prevents a trade-vs-reset race. See PR #1208 for the original
advisory-lock landing.
Authorizations
Issue from /v1/keys (or admin-issued for enterprise tier).
Headers
Path Parameters
Response
Successful Response
Tenant identity for a PROP_FIRM wallet (prop-firm plan §8
managed_by). Drives the native Managed by {display_name} label.
Governance-account summary for a PROP_FIRM wallet (prop-firm plan §8
b2b_account). account_id is the UUID as a string; stage is one
of demo|challenge|funded (rendered as the Demo/Challenge/Funded
badge); status one of active|closed|archived.