fix(platform-wallet): raise the invitation cap to cover the contested username tier - #4362
Conversation
… username tier MAX_INVITATION_DUFFS 5_000_000 -> 26_000_000 (0.05 -> 0.26 DASH). Required for existing Android functionality: the Android wallet has funded contested (premium-name) invitations at 0.25 DASH since 2024 (DASH_PAY_FEE_CONTESTED, dash-wallet Constants.java). Its legacy dashj path imposes no cap, so contested invitations have always worked pre-cutover; the moment a wallet commits the dashj->SDK cutover, create_invitation becomes the only route and every contested invitation is rejected pre-broadcast with 'invitation amount 25000000 exceeds the cap 5000000 duffs' - observed on device 2026-08-09, an endless-retry loop in the field. The 0.05 value's own doc deferred the contested tier 'until contested-name-via-invite claim exists; raise this cap when it does'. That condition is met: claim_invitation is amount-agnostic and contested-invite claims are verified working in QA. The cap remains a client-side leaked-link bound, not consensus; both the dashj and shielded invitation paths already mint 0.25 bearer links today, so 0.05 here protected nothing while breaking path parity. 0.26 = 0.25 contested fee + margin for the create/claim fees, matching the Android wallet's rounded contested guidance. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 32 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (12)
Comment |
|
🕓 Ready for review — next in queue (commit 7b6ca46) |
thepastaclaw
left a comment
There was a problem hiding this comment.
Final validation — Codex/Sol only (Phase 2 disabled)
The Rust cap change correctly allows the 25,000,000-duff contested tier and remains client-side rather than consensus-critical. Two in-scope follow-ups remain: synchronize repository consumers that mirror the old cap, and add regression coverage for the changed boundary.
Source: codex general reviewer backend gpt-5.6-sol; codex rust-quality reviewer backend gpt-5.6-sol; final codex verifier backend gpt-5.6-sol; openclaw-agent/cliproxy/gpt-5.6-sol was orchestration-only and is not reviewer evidence.
Validated zero-blocker Codex/Sol precheck evidence was promoted to final because Phase 2 (Sonnet/Opus) is temporarily disabled. This is Codex/Sol-only final validation, not Codex + Sonnet/Opus coverage.
Review provenance
- Codex reviewers:
gpt-5.6-sol— general (completed),gpt-5.6-sol— rust-quality (completed) - Verifier:
gpt-5.6-sol— verifier - Sonnet/Opus: not run (Phase 2 disabled — temporary Codex/Sol-only final)
- Secondary pass: disabled (
temporary_phase2_sonnet_disable)
🟡 2 suggestion(s)
🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.
In `packages/rs-platform-wallet/src/wallet/identity/network/invitation.rs`:
- [SUGGESTION] packages/rs-platform-wallet/src/wallet/identity/network/invitation.rs:60: Update clients that still mirror the old invitation cap
This change makes the repository's explicit cap mirrors inconsistent with the Rust source of truth. `packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/DashPay/CreateInvitationSheet.swift` still defines `maxInvitationDuffs` as `5_000_000`, and its amount parser rejects larger values, so that bundled client cannot create a 0.25 DASH contested invitation even though the corrected Rust API accepts it. The associated Swift text, Kotlin KDoc and example guidance, `Info.plist`, and `docs/dashpay/DIP15_INVITATIONS_SPEC.md` also still advertise the old 0.05 DASH limit. Update these mirrors to 26,000,000 duffs so the client behavior and documentation match the newly raised cap.
- [SUGGESTION] packages/rs-platform-wallet/src/wallet/identity/network/invitation.rs:60: Add a regression test for the contested invitation amount
No test independently exercises the amount-cap branch or references `MAX_INVITATION_DUFFS`, so reverting this constant to 5,000,000 would reproduce the reported regression while leaving the existing suite green. Extend the durability-gate harness with independently stated boundaries: 25,000,000 duffs should pass amount validation and reach the expected persistence-capability error, while `MAX_INVITATION_DUFFS + 1` should fail immediately with `InvalidIdentityData`. This directly pins both the contested tier and the upper-bound rejection without broadcasting funds.
| /// Android wallet has funded contested invitations at 0.25 since 2024, so the | ||
| /// deferral is over. (The pre-merge 0.01 iteration was below even a usable | ||
| /// non-contested invitation and rejected its own onboarding default.) | ||
| pub const MAX_INVITATION_DUFFS: u64 = 26_000_000; |
There was a problem hiding this comment.
🟡 Suggestion: Update clients that still mirror the old invitation cap
This change makes the repository's explicit cap mirrors inconsistent with the Rust source of truth. packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/DashPay/CreateInvitationSheet.swift still defines maxInvitationDuffs as 5_000_000, and its amount parser rejects larger values, so that bundled client cannot create a 0.25 DASH contested invitation even though the corrected Rust API accepts it. The associated Swift text, Kotlin KDoc and example guidance, Info.plist, and docs/dashpay/DIP15_INVITATIONS_SPEC.md also still advertise the old 0.05 DASH limit. Update these mirrors to 26,000,000 duffs so the client behavior and documentation match the newly raised cap.
source: ['codex']
| /// Android wallet has funded contested invitations at 0.25 since 2024, so the | ||
| /// deferral is over. (The pre-merge 0.01 iteration was below even a usable | ||
| /// non-contested invitation and rejected its own onboarding default.) | ||
| pub const MAX_INVITATION_DUFFS: u64 = 26_000_000; |
There was a problem hiding this comment.
🟡 Suggestion: Add a regression test for the contested invitation amount
No test independently exercises the amount-cap branch or references MAX_INVITATION_DUFFS, so reverting this constant to 5,000,000 would reproduce the reported regression while leaving the existing suite green. Extend the durability-gate harness with independently stated boundaries: 25,000,000 duffs should pass amount validation and reach the expected persistence-capability error, while MAX_INVITATION_DUFFS + 1 should fail immediately with InvalidIdentityData. This directly pins both the contested tier and the upper-bound rejection without broadcasting funds.
source: ['codex']
… FFI Review follow-up: the SwiftExampleApp mirrored MAX_INVITATION_DUFFS (and the floor) as hardcoded constants, so the bundled iOS client still rejected the contested tier this PR unlocks. Rust now owns the only copy: - FFI getters platform_wallet_invitation_max_duffs / _min_duffs return the library constants (pinned by a bridge test); MIN_INVITATION_DUFFS joins the network module re-export. - SwiftDashSDK bridges them as ManagedPlatformWallet.maxInvitationDuffs / minInvitationDuffs; CreateInvitationSheet reads those and renders its help copy from the values, so no numeric mirror remains in Swift. - Stale textual mentions of the old 0.05 cap updated (Info.plist comment, Kotlin KDoc, QA004, DIP15 spec). Verified: platform-wallet-ffi + platform-wallet tests green, clippy clean, build_ios.sh sim+mac (incl. SwiftExampleApp simulator build) and swift test pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Android counterpart of the Swift single-sourcing commit: the Kotlin example app's help copy re-typed the 0.003-0.05 DASH bounds and went stale when the cap moved. Rust stays the only copy: - JNI exports DashpayNative.invitationMaxDuffs/invitationMinDuffs bridging platform_wallet_invitation_max_duffs/_min_duffs. - Dashpay companion exposes maxInvitationDuffs/minInvitationDuffs; the createInvitation KDoc references them instead of restating the numbers. - KotlinExampleApp CreateInvitationSheet renders its bounds copy from the values (BigDecimal, locale-independent) — no numeric mirror remains. Verified: rs-unified-sdk-jni clippy clean, gradle :sdk:assembleDebug + :sdk:testDebugUnitTest + :app:assembleDebug all pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## v4.2-dev #4362 +/- ##
=========================================
Coverage 87.63% 87.63%
=========================================
Files 2670 2670
Lines 339449 339516 +67
=========================================
+ Hits 297467 297533 +66
- Misses 41982 41983 +1
🚀 New features to boost your workflow:
|
Supersedes #4351 — same change, recreated on a
dashpay/platformbranch per repo policy (no more personal-fork PRs). Commits and authorship unchanged; full review history on #4351.Required for existing Android functionality
The Android wallet has funded contested (premium-name) invitations at 0.25 DASH since 2024 (
DASH_PAY_FEE_CONTESTED, dash-walletConstants.java:332). Its legacy dashj invitation path imposes no cap, so contested invitations have always worked pre-cutover. The moment a wallet commits the dashj→SDK cutover,create_invitationbecomes the only route — and every contested invitation is rejected pre-broadcast:Observed on a device 2026-08-09 as an endless confirm/retry loop (the app-side loop is fixed separately; the capability gap is this cap). A contested L1 invitation has never succeeded through the SDK path — the 0.25-vs-0.05 contradiction has existed since the path was first wired.
Why raising is safe and sanctioned
claim_invitationis amount-agnostic (no cap at claim), and contested-invite claims are verified working in QA.0.26 = the 0.25 contested fee + margin for the create/claim fees, matching the Android wallet's rounded contested guidance.
MIN_INVITATION_DUFFSand all boundary tests are relative to the constant and unchanged;platform-walletlib: 610 passed / 0 failed.🤖 Generated with Claude Code
Summary by CodeRabbit