New price sourcing - #17
Merged
Merged
Conversation
llbartekll
added a commit
that referenced
this pull request
May 21, 2026
PR 1 of the row #16 migration (new-user identity + DPNS username from DashSync to SwiftDashSDK). Scaffolding only, behind a disabled `DASHPAY_SWIFT_SDK_REGISTRATION` flag — nothing calls these files yet, DashSync remains the live path. PR 2 wires `DWDashPayModel.m` + `DWCheckExistenceUsernameValidationRule.m` into the new path. Migration doc updates (re-verified 2026-05-20): - Row #16 / #17 / #19 flipped to 🟢 ready; row #18 flipped from 🔴 to 🟡 (SDK APIs exist, no example walkthrough). Earlier "6+ FFI signature mismatches" claim resolved upstream via 33fde4e67f (cbindgen ABI), e22f816a2e (asset-lock proofs), c556a86db2 (KeychainSigner sweep), e9e56f3636 (account_index plumbed through). - Hard Blockers: struck through #16 with the four resolving commits. - Recommended order Wave 3 marked unblocked for #16/#17/#19. New files in `DashWallet/Sources/Infrastructure/SwiftDashSDK/Identity/`: - `DWRegistrationPhaseAdapter.swift` — pure mapping collapsing the SDK's 5 internal phases (controller phase + `PersistentAssetLock.statusRaw`) onto the existing 3-state `DWDPRegistrationState` UI enum. Unit-tested. - `DWIdentityRegistrationController.swift` — `@MainActor ObservableObject` phase holder (idle / preparingKeys / inFlight / completed / failed), ported from the SwiftExampleApp reference and stripped to a pure state carrier (v1 pins identityIndex=0; coordinator drives transitions). - `DWIdentityAuthorizer.swift` — async PIN/biometric gate wrapping `DSAuthenticationManager.authenticate`. Mirrors the private `SendAuthorizer` pattern from `WalletSendService.swift:129-172`. - `DWIdentityRegistrationCoordinator.swift` — `@MainActor` singleton orchestrating the full chain: PIN gate → `prePersistIdentityKeysForRegistration` → `registerIdentityWithFunding` → `registerDpnsName`. Polls `PersistentAssetLock.statusRaw` every 0.5s while `.inFlight` for the 3-state UI mapping. Mirrors success into `DWGlobalOptions.dashpayUsername` + `dashpayRegistrationCompleted` so the 87 existing Obj-C identity-read sites keep working until row #17 migrates them individually. - `DWIdentityRegistrationBridge.swift` — `@objc @mainactor @objcMembers` facade for `DWDashPayModel.m` / `DWCheckExistenceUsernameValidationRule.m`. Cached `@objc` state mirrored from the coordinator via one `Publishers.CombineLatest($phase, $assetLockStatus)` subscription (passing emitted values directly avoids the `@Published` willSet re-read race). Posts `DWDashPayRegistrationStatusUpdatedNotification` on every transition. Tests: `DashWalletTests/DWRegistrationPhaseAdapterTests.swift` — 12 cases covering the full mapping matrix plus the failure-classification edge. Project file: - `DASHPAY_SWIFT_SDK_REGISTRATION=0` appended to all 5 GCC blocks that already contain `DASHPAY=1` (defined-but-falsy; PR 3 flips per-config). - New Swift files registered on the `dashpay` target only — they reference DashPay-only Obj-C symbols (`DWDP_MIN_BALANCE_TO_CREATE_USERNAME`, `DWGlobalOptions.dashpayUsername` / `dashpayRegistrationCompleted`), which don't exist in the `dashwallet` target build. - Test file registered on the `DashWalletTests` target. v1 scope (documented for follow-up): - Invitations stay on DashSync (no SDK equivalent for `DSBlockchainInvitation`). - Existing DashSync identities not migrated — keys live in DashSync's keychain, not in `WalletStorage`. Future "import identity" stage. - No crash-resume via `resumeIdentityWithAssetLock` (deferred to v2). - Platform Payment funding path (`registerIdentityFromAddresses`) not wired — users with Platform credits but no Core balance still see the 0.03 Dash error. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
llbartekll
added a commit
that referenced
this pull request
May 21, 2026
PR 2 of the row #16 migration. With `DASHPAY_SWIFT_SDK_REGISTRATION` still at `0`, every `#if` branch is unselected, every `#else` is byte-identical to pre-PR-1 behavior — no runtime change. Flipping the flag (PR 3, testnet only) activates the new path end-to-end. `DWIdentityRegistrationBridge.swift`: - Add `@objc public static let stateChangedNotification` (a new internal name, `DWIdentityRegistrationBridgeStateChangedNotification`) and have `refreshFromCoordinator(...)` post it instead of the canonical `DWDashPayRegistrationStatusUpdatedNotification` it was posting in PR 1. Reason: NSNotificationCenter delivers in registration order, so existing UI consumers of the canonical name (`HomeViewModel.swift:855`, `MainTabbarController.swift:129`, `DWUserProfileContainerView.m:93`) could fire before `DWDashPayModel` updated its `registrationStatus` and read stale model state. Now only `DWDashPayModel` observes the bridge, mirrors state, and posts the canonical notification — single ordered hop. Docstring on `wireCoordinatorObservation` updated to reflect this. `DashWallet/Sources/UI/Home/Models/DWDashPayModel.m`: - Add an observer in `init` for the bridge's `stateChangedNotification`, guarded by `#if DASHPAY_SWIFT_SDK_REGISTRATION`. - New selector `bridgeRegistrationStateChanged:` (also `#if`-guarded) that reads the bridge's cached `@objc` state, mirrors it into `self.registrationStatus` / `self.lastRegistrationError`, and posts the canonical notification. On `bridge.isCompleted` it intentionally does NOT call `completeRegistration` because that method nils `DWGlobalOptions.dashpayUsername` (assuming `wallet.defaultBlockchainIdentity.currentDashpayUsername` becomes the source of truth), but the SDK path has no DashSync identity — nil-ing would make `self.username` permanently nil and break the 87 downstream Obj-C identity-read sites until row #17 migrates them. Mirrors the other success effects (`shouldShowInvitationsBadge = YES`, clear `registrationStatus`, post canonical) inline. - `createUsername:invitation:` routes the new-user no-invitation case (`wallet.defaultBlockchainIdentity == nil`) through `[DWIdentityRegistrationBridge.shared startCreateUsername:completion:]` under `#if`. Existing-identity case falls through to unchanged DashSync code. Invitation branch (lines 135-168) untouched. - The bridge completion is a safety net for early-exit failures that don't reach a terminal-phase notification — SDK preconditions (no wallet / no network / no model container) throw before the controller is wired, and auth-cancel calls `resetState()` which clears `bridge.currentUsername` before the model observer reads it. In those cases `dashpayUsername` (cached at line 131) would stay set forever. The completion clears it and surfaces the error when `registrationStatus == nil` (i.e. the notification path didn't surface a failed state). For mid-flight failures the notification path already wrote a `.failed` status, so the early-return preserves that UI state. `DashPay/Presentation/Setup/CreateUsername/Models/DWCheckExistenceUsernameValidationRule.m`: - Conditional `#import "dashwallet-Swift.h"` under `#if DASHPAY_SWIFT_SDK_REGISTRATION`. - Wrap the body of `performValidationWithUsername:` in `#if / #else`. The `#if` branch calls `[DWIdentityRegistrationBridge.shared checkAvailability:completion:]` with the same `DWUsernameValidationRuleResult` semantics (available=Valid, taken=InvalidCritical, error=Error). The `#else` keeps the existing `DSIdentitiesManager.searchIdentityByDashpayUsername:` call unchanged (the `DSIdentitiesManager *manager` local moves into the `#else` block since the new path doesn't need it). The `MOCK_DASHPAY` early-return and the debounce mechanism in `validateText:` are preserved across both branches; the `self.username == username` guard inside the completion handles stale-result discarding. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
llbartekll
added a commit
that referenced
this pull request
May 21, 2026
End-to-end verified on testnet 2026-05-20 — first DashPay identity created from dashwallet-ios via SwiftDashSDK (identity `5150b96d…`, name `433v2gnfdggdfs.dash`). The full coordinator chain — PIN gate → `prePersistIdentityKeysForRegistration` → `registerIdentityWithFunding` → `registerDpnsName` — completed cleanly with `PersistentAssetLock` transitioning `1 → 2 → 4` (Broadcast → InstantSendLocked → Consumed) on a funded testnet wallet. Three things land in this commit: 1. **Form rewire** — `CreateUsernameViewModel.submitUsernameRequest` was running mock code (write a fake `UsernameRequest` DTO with a random UUID identity to `UsernameRequestsDAOImpl.shared`, set `UsernamePrefs.shared.requestedUsernameId`, sleep 2s, return true). The actual `dashPayModel.createUsername(...)` call was commented out. Replaced with the real call; the mock DAO write, `joinDashPayDismissed` toggle, and fake sleep are gone. Signature now takes `dashPayModel: DWDashPayProtocol` — the SwiftUI view already holds it via `@State var dashPayModel: DWDashPayProtocol`, so both call sites in `CreateUsernameView` (the simple Continue path at line 143 and the post-verify-identity confirm-spend path at line 206) just thread it through. 2. **`checkIfBlocked` short-circuit** — was sleeping 2s and setting `usernameBlockedRule = .warning`, which forced the user through the contested-username "verify identity" sheet on Continue. The sheet's voting-prompt copy + verify-identity proof URL flow is out of scope for the SDK v1 migration (contested-username resolution lives in the SDK's `dpnsGetContestedVoteState` / `dpnsGetCurrentContests` APIs but we don't surface them yet). Set `.valid` directly so Continue hits the simple submit path. Real DPNS availability detection lives in `DWIdentityRegistrationBridge.checkAvailability` and is exercised by the legacy `DWCheckExistenceUsernameValidationRule` flow if/when that flow becomes the active UI. 3. **Flag flip to `=1`** — `DASHPAY_SWIFT_SDK_REGISTRATION=0` → `DASHPAY_SWIFT_SDK_REGISTRATION=1` in all 5 GCC preprocessor blocks that contain `DASHPAY=1`. Same value everywhere; not scoped per-configuration. Combined with the earlier PR 1 (`b91c0a144`) + PR 2 (`5291371f4`) wiring, this activates the SDK code path end-to-end. `dashwallet` target is unaffected (new files only registered on the `dashpay` target). `DASHSYNC_MIGRATION.md` updates: - Row #16 Status column flipped from `—` → `🌗 Flipped` and a new detailed "Where we are" entry added at the top of the doc with commit hashes (`b91c0a144`, `5291371f4`, and this one), the testnet verification identity ID + name, and the known v1 gaps (orphan asset-lock on crash, half-state on DPNS-failure retry, Platform Payment funding still unwired). **Out of scope** (separate stages): - Invitation branch (`DSBlockchainInvitation.acceptInvitation:`) stays on DashSync — no SDK equivalent. - Existing DashSync identities (very rare in this branch state) fall through to the unchanged DashSync path. Future "import DashSync identity into SwiftDashSDK" stage needed. - Contested-username voting flow bypassed. - Platform Payment funding (`registerIdentityFromAddresses`) — users with Platform credits but no Core balance still see the 0.03 Dash form check. - Cleanup of the now-dead mock viewmodel fields (`currentUsernameRequest`, `hasUsernameRequest`, `fetchUsernameRequestData`, `cancelRequest`, `updateRequest`, `hasRequests(for:)`, the `dao` + `prefs` properties) — separate cleanup PR. - Row #17 (`DSBlockchainIdentity` read-site migration, 87 files) is now unblocked but separate. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
llbartekll
added a commit
that referenced
this pull request
May 25, 2026
After PR 5 ships SwiftDashSDK identity registration (including Platform-Payment funding), a wallet whose only identity lives in SwiftData's `PersistentIdentity` — with no DashSync `defaultBlockchainIdentity` reconstruction — was invisible to the home-screen nav-bar avatar. Row #17 proper migrates the ~89 other DashSync `DSBlockchainIdentity` read sites across DashPay UI; this focused stage closes only the user-visible avatar gap so the SDK identity flow is exercisable end-to-end without waiting for the full read-site migration. - `DWDashPayProtocol.hasIdentity` (new) — OR of DashSync's `defaultBlockchainIdentity != nil` and `DWGlobalOptions.dashpayRegistrationCompleted`. Consumers that only need "does this wallet have a DashPay identity?" read this instead of unwrapping a `DSBlockchainIdentity`. Implemented in `DWDashPayModel`. The legacy `blockchainIdentity` getter is unchanged and still returns nil for SDK-only identities — row #17 proper migrates each consumer individually. - `HomeViewController` avatar visibility consults `hasIdentity` in both the legacy `homeView(_:didUpdateProfile:)` delegate callback and a new `refreshIdentityAvatar()` helper. The helper is called from three places: viewDidLoad (seed on launch for re-launch with an existing identity), the legacy delegate, and a new observer on `DWDashPayRegistrationStatusUpdated` (so SDK registrations surface live without waiting for a DashSync delegate fire). The original `DWDPAvatarView` + `UIBarButtonItem(customView:)` + `UITapGestureRecognizer` shape is preserved unchanged. - `HomeViewController.profileAction()` branches on the underlying `DSBlockchainIdentity` object. DashSync-side identities continue to open `RootEditProfileViewController` (byte-equivalent to the pre-change behavior). SwiftDashSDK-only identities open the new read-only `SDKIdentityProfileSheet` instead — the legacy editor unwraps `DSBlockchainIdentity` properties and would crash on a nil identity, so it isn't safe for the SDK path until row #17 proper migrates it. - `SDKIdentityProfileSheet` (new SwiftUI view, dashpay target only) shows the registered username (placeholder avatar + first initial), the 32-byte identity ID as monospaced hex with a copy-to-clipboard button, the wallet's Platform-credit balance (read from `SwiftDashSDKWalletState.platformPaymentCredits` via the PR 5 surface), and a hint that editing is coming in a future update. Registered on the `dashpay` target only — matches the Identity/ pattern from PR 1. What stays for row #17 proper (out of scope here): - The avatar's per-user rendering (letter / branded color / DashPay profile image inside `DWDPAvatarView`) is still driven by `DSBlockchainIdentity`. SDK-only identities get the avatar view's default placeholder — a dash-blue circle with no letter. - `DWEditProfileViewController`, `DWCurrentUserProfileView`, `DWDPUpdateProfileModel` and the other ~85 DashSync-reading sites stay as-is. - Contact request flows (`DWDashPayModel.m:260,273` crash on nil identity if invoked from contacts UI; that UI isn't reachable from the avatar tap on SDK-only identities). - DashPay profile writes (`createDashPayProfile`/`updateDashPayProfile`). Deliberately untouched (per ongoing debug needs): - `MainMenuViewController` FIXME debug edits — restore before shipping. - `JoinDashPayViewModel.checkUsername()` state derivation. - `HomeViewModel.checkJoinDashPay()` banner gating. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
llbartekll
added a commit
that referenced
this pull request
May 25, 2026
Centralise DashPay current-user reads behind DWCurrentUserIdentityInfo and route profile writes through SwiftDashSDK. Row #17 stage A already surfaced SDK identities on the home-screen avatar + tap — this commit finishes the in-scope read sites (avatar render, profile display, invitation link, payment-side identity gate) and the profile editor's write path. Pre-existing DashSync identities (rare in this branch) keep working via fallbacks; full retirement lands with Row #25. New infrastructure (dashpay target): - DWCurrentUserIdentityInfo: @objc @mainactor lookup. Snapshot of (username, displayName, avatarURL, publicMessage, identityIdHex) invalidated on DWDashPayRegistrationStatusUpdated and DWIdentityRegistrationBridge.stateChangedNotification. Resolves PersistentIdentity from SwiftData, reads via wallet.managedIdentity(identityId:) → getDpnsNames() + getDashPayProfile(). Falls back to DWGlobalOptions.dashpayUsername for the post-register sync gap. - DWProfileUpdateCoordinator: async @mainactor write path with PIN gate, KeychainSigner, and create-vs-update verb flip on cache- mismatch error from the SDK. - DWProfileUpdateBridge: @objc completion-based facade. JPEG-encodes the cropped UIImage at quality 0.8 for DashPayProfileUpdate.avatarBytes. Migrated reads: - DWDPAvatarView: configureAsCurrentUser. Contact-side setBlockchainIdentity: kept for Row #18. - DWEditProfileAvatarView: setImageForCurrentUser. - DWCurrentUserProfileView: reloadFromCurrentUser. The legacy setBlockchainIdentity: setter now forwards to it. reloadAttributedData reads via a new DWCurrentUserTitleSubtitleAttributedString free function alongside the existing DSBlockchainIdentity+DWDisplayTitleSubtitle category. - DWEditProfileViewController: displayName / aboutMe / avatar URL all prefill from the helper. Drops the non-MOCK assertion that blockchainIdentity is non-nil. unsavedAvatarImage retains the cropped UIImage so the SDK write path can hand bytes downstream. - DWInvitationLinkBuilder: inviter profile fields from the helper. - DWDashPayModel.username: prefer helper, fall back to DashSync + DWGlobalOptions. - DWPayModel.refreshOptions: DashPay send-button gate via helper.hasIdentity. Migrated write: - DWDPUpdateProfileModel.updateWithDisplayName:aboutMe:avatarURLString:avatarImage: branches on wallet.defaultBlockchainIdentity. non-nil → legacy DashSync sign-and-publish. nil → DWProfileUpdateBridge. The new avatarImage parameter threads from RootEditProfileViewControllerDelegate through HomeViewController + MainMenuViewController's DelegateInternal. - SDKIdentityProfileSheet: optional onEditTapped callback drives a new Edit button. HomeViewController.profileAction chains into RootEditProfileViewController on the tap so SDK identities can edit their profile end-to-end now. Out of scope (Row #18 / Row #25 / future): - DWUserProfileHeaderView, InvitationBottomView, DWNotificationsProvider, DWDashPayContactsUpdater, DWDashPayContactsActions — contact-side rendering and contacts subsystem. - DWPaymentProcessor + DWPaymentOutput+DWView identity reads — pass DSBlockchainIdentity into deeper BIP-70 / friend-status machinery. - Contested-name voting (still bypassed since PR 3). Carveouts preserved untouched per user request: - MainMenuViewController FIXME: TEMPORARY debug edits - JoinDashPayViewModel.checkUsername - HomeViewModel.checkJoinDashPay Verified: dashpay scheme builds clean. End-to-end testnet verification pending; the read paths render via the helper's snapshot + SDWebImage URL load, and the write path calls into the existing SDK profile APIs proven by the SwiftExampleApp. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
llbartekll
added a commit
that referenced
this pull request
May 28, 2026
- Mark "Known SDK issues §1" (`could not decode data contracts query`) as RESOLVED 2026-05-27 via the Platform protocol v11 pin (`SwiftDashSDKHost.swift` → `SDK(network: protocolVersion: 11)`, backed by upstream PR #3734). - Row #17 stage B "Where we are": drop the "blocked by upstream SwiftDashSDK bug" caveat; profile editing is end-to-end verified. - Row #17 functional-table row: same cleanup. - Row #18a entry: rephrase the "status view comes back once upstream is fixed" line — it's now a scope/product decision, not a blocker. - Add a new "Where we are" entry covering the v11 pin + DPNS lookup finalisation: `usernames: [String]` exposure, cold-launch cache fix, wallet-side query, Edit Profile entry-point gate on `hasIdentity`, tab-bar restore workaround, and the `DASHPAY_SWIFT_SDK_REGISTRATION` flag retirement. - Row #19 (DPNS lookup) flips from "—" to 🌗 Flipped; consumers column splits availability check (done) vs. prefix search (`DWUserSearchModel`, travels with #18 because the consumer factory expects `DSBlockchainIdentity`). - Wave 3 row: update from "not started" to "Flipped for #16/#17/#19, #18 still pending". - Row #16 "Where we are": flag retirement footnote so a future reader doesn't grep for it and find only stale references. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
depends on dashpay/dashsync-iOS#57