Skip to content

feat(userflags): surface the username minimum balance flag - #1322

Merged
bmc08gt merged 2 commits into
code/cashfrom
feat/userflags-username-price
Aug 24, 2026
Merged

feat(userflags): surface the username minimum balance flag#1322
bmc08gt merged 2 commits into
code/cashfrom
feat/userflags-username-price

Conversation

@bmc08gt

@bmc08gt bmc08gt commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

UserFlags gained username_min_balance upstream — the USDF amount, in quarks, a user must hold across all currencies before setting a username. This vendors the proto change and maps the field through to the domain model and the debug flag editor.

It gates the username claim flow whose service layer landed in #1320. That flow has no UI yet, so nothing reads this value so far.

Read-only, not overridable

Every other Fiat flag is overridable in the debug editor; this one isn't. The practical cost: exercising the claim gate locally means having the server send a non-zero value, since you can't force one from the editor.

ReadOnlyEntry holds a Boolean, so the amount goes in readOnlyTextEntries next to tipPresets, formatted with Fiat.FormattingRule.Truncated to match how WithdrawalFeeAmount renders.

Default is Fiat.Zero

The fee and price flags (newCurrencyPurchaseAmount, newCurrencyFeeAmount) default to Fiat.MAX_VALUE — for an amount the user pays, an unknown value should fail closed. This one is a minimum balance to hold, the same shape as minimumHolderValue, so it takes that flag's Fiat.Zero default instead.

Zero means an absent flag leaves the gate open and the server's INSUFFICIENT_BALANCE result stays the real enforcement, rather than hard-blocking a claim the server would have allowed. The tradeoff to be aware of: a silent mapping failure would look identical to "no gate configured."

The resemblance to minimumHolderValue stops at the default. minimumHolderValue is a per-mint threshold — TokenDiscoveryViewModel checks it against one token's balance — whereas username_min_balance is cumulative across every mint. Whoever writes the claim gate should compare it against the summed balance (LocalFiat.underlyingTokenAmount), not a single token's. The domain property carries that note in a comment.

CachedFlags needed the field too

UserFlagsCoordinator holds a @Serializable cache model whose toDomain() reconstructs the whole UserFlags, so it doesn't compile without the new field. It defaults to zero quarks so payloads cached before this change still decode — the read path does runCatching { json.decodeFromString<CachedFlags>(raw) }.getOrNull() ?: return, which discards the entire cached flag set on a decode failure. An undefaulted field would blank the flags on the first launch after upgrade.

Adds UserFlags.username_min_balance, the USDF amount in quarks a user
must hold across all currencies before setting a username. Vendored from
flipcash2-protobuf-api at HEAD; opencode was already current.
Maps UserFlags.username_min_balance through to the domain model and the
debug flag editor as a read-only entry. It gates the username claim flow
added in #1320, which has no UI yet, so nothing reads it so far.

The default is Fiat.Zero rather than Fiat.MAX_VALUE. This is a minimum
balance to hold, like minimumHolderValue, not a price to pay like
newCurrencyPurchaseAmount. An absent flag should leave the gate open and
let the server answer with INSUFFICIENT_BALANCE, not hard-block a claim
the server would have allowed.

CachedFlags also carries the field, since its toDomain() reconstructs the
whole UserFlags. It defaults to zero quarks so payloads cached before this
change still decode -- UserFlagsCoordinator drops the entire cached flag
set when decodeFromString fails, so an undefaulted field would blank the
flags on the first launch after upgrade.

ReadOnlyEntry holds a Boolean, so the amount goes in readOnlyTextEntries
formatted with Fiat.FormattingRule.Truncated, matching WithdrawalFeeAmount.
@github-actions github-actions Bot added type: feature New functionality area: network gRPC, connectivity, API, exchange rates and removed type: feature New functionality labels Aug 24, 2026
@bmc08gt
bmc08gt merged commit c95ab32 into code/cash Aug 24, 2026
2 of 3 checks passed
@bmc08gt
bmc08gt deleted the feat/userflags-username-price branch August 24, 2026 20:16
bmc08gt added a commit that referenced this pull request Aug 25, 2026
)

`usernameMinBalance` landed on UserFlags in #1322 without a default, so the test
fixture no longer compiles and every PR against code/cash fails:

    ResolvedUserFlagsTest.kt:140:5 No value passed for parameter 'usernameMinBalance'

The flag resolves with FieldOverride.None, so it needs no OverrideCase — only the
fixture value and the assertion the first test's name already promises.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: network gRPC, connectivity, API, exchange rates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant