Fix displaying previous shapeshift bitcoin transaction - #18
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 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 25, 2026
Detect contested-eligible labels client-side via the SDK FFI helper `dash_sdk_dpns_is_contested_username`, warn the user with an orange callout + confirmation alert in Create Username, and defer the `DWGlobalOptions.dashpayUsername` + `dashpayRegistrationCompleted` mirror writes until vote resolution. - `DWContestedNameStatusService` — thin UserDefaults wrapper: `pendingLabel`, `recordSubmission(label:)`, `clearPending()`, static `isContestedLabel(_:)` FFI predicate. Single in-flight contested submission per identity (v1). - `DWIdentityRegistrationCoordinator` branches after successful `registerDpnsName`: contested → service.recordSubmission + best- effort `syncContestedDpnsNames`; `handlePhaseChange` skips the global-mirror writes when the bookmark matches. - `DWCurrentUserIdentityInfo.computeSnapshot` filters the pending contested label out of `getDpnsNames()` results so Edit Profile / SDK profile sheet / invitation links / payment memos don't surface a contested-but-not-yet-owned name. - `HomeViewController.viewDidAppear` calls a new `syncFromNetwork()` on the helper to refresh blockchain DPNS names — exposes the upstream `GetDataContractsRequest.version = None` SDK bug which blocks `syncDpnsNames` (same root cause as profile writes). - StorageExplorer `FieldRow` gets tap-to-copy with brief checkmark feedback — useful for copying identity IDs / Platform addresses out of the debug view. - `DWDPUpdateProfileModel.update(...)` reads the *real* `defaultBlockchainIdentity` (not the MOCK_DASHPAY synthetic getter) so the SDK-vs-DashSync branch picks the right path under `MOCK_DASHPAY=YES`. Status view + per-vote refresh deliberately omitted — both rely on `fetchContestVoteState` / `syncDpnsNames` which hit the same data- contracts gRPC bug. Can come back once the upstream fix lands. Carveouts respected (per repeated user instruction): MainMenu FIXME debug edits, JoinDashPayViewModel.checkUsername(), HomeViewModel.checkJoinDashPay(), UsernameRequestsDAO, UsernamePrefs.requestedUsernameId, RequestDetailsViewController, VerifyIdentityScreen, VotingViewModel — none touched. Side effects of those carveouts during voting: Join DashPay banner stays visible, home-screen avatar stays hidden (`dashpayRegistrationCompleted` stays NO until resolution). 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>
llbartekll
added a commit
that referenced
this pull request
Jun 18, 2026
CoinJoin row #20 corrected: mixing is being dropped (legacy mixing UI already retired), not migrated. The one capability that moves over — recovering/sweeping already-mixed coins into spendable balance — is implemented on both sides via ManagedCoreWallet.sweepCoinJoinAccount (platform PR #3817, awaiting merge). CoinJoin is no longer the 'keep DashSync linked indefinitely' hard blocker. Updated the functional table, 'Where we are', Hard blockers, and Wave 6. Easy-win status promotions: - #13 Backup seed phrase: Flipped -> Done (backup read is 100% SwiftDashSDK, no fallback; adapter already retired). - #19 DPNS username lookup: Flipped -> Done (availability check fully on SDK; prefix search carved out to #18; dead request residue removed). - #10 PIN-change half: close-out note (mirror retired permanently, stays on DashSync by decision). - #7: isMinimal noted as removed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
llbartekll
added a commit
that referenced
this pull request
Jul 6, 2026
New "Where we are" entry for the five reader groups moved off DSWallet.allTransactions (tax CSV, ZenLedger, gift-card details, CrowdNode withdrawal limits + online-account scans, request-amount receive); #6-satellites deferred list and the #11 audit-correction reader inventory updated — the deprecated DSTransaction filter adapter is gone and the only remaining allTransactions consumers are the DashPay profile data source (#18) and the onboarding stub. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
QuantumExplorer
added a commit
that referenced
this pull request
Jul 8, 2026
… DashSync subsystem Migration Row #18 — the contacts feature (dead at runtime since the post-M6 DashSync freeze) is rebuilt end-to-end on SwiftDashSDK and the entire DashSync implementation is removed in the same change. E2E-verified on testnet against SwiftExampleApp driving the far side: request sent → reciprocated → established → paid both directions. New SDK boundary (Sources/Infrastructure/SwiftDashSDK/Contacts/): - SwiftDashSDKContactsService: SwiftData read model (established = both direction rows, single row = pending; debounced NSManagedObjectContextDidSave refresh), PIN-gated send/accept via DWIdentityAuthorizer + KeychainSigner, ignoreSender (replaces the legacy decline, which was a TODO stub that faked failure), DPNS prefix search + reverse lookup (dpnsGetUsername, base58), contact meta (alias/note/hide via EstablishedContact + flushPersist), notifications read-state on the legacy DWGlobalOptions slot, and the payments projection (see below). - DWIdentityKeyUpgrader: dashwallet registration derives AUTHENTICATION keys only, so identities registered here could not send contact requests. Before the first contact action, one IdentityUpdate adds the missing ENCRYPTION + DECRYPTION keys (ECDSA, MEDIUM, bounds SingleContractDocumentType(DashPay, "contactRequest") — Drive rejects unbound or contract-level bounds). - DashPay background sync (15s six-step pass) start/stop wired into PlatformAddressSyncCoordinator alongside BLAST + shielded. - SDK.enableLogging installed at host init — the app previously ran the whole SDK with Rust diagnostics muted. Payments correctness (found live-testing): - PersistentDashpayPayment rows exist only via the app-pulled projection (PlatformWalletManager.refreshDashPayPayments); the Rust persister never pushes them, and Sent entries are unrecoverable if the app dies before a projection. The service now projects on every sync pass, at most once a minute on snapshot refresh, on profile open, and immediately after every successful send. - WalletSendService.sendToContact: pay-to-contact through the send boundary — spend-auth gate, then the single-shot SDK sendDashPayPayment (derives the DIP-15 address Rust-side), invoked only after the user's explicit Pay tap. Returns the exact network fee of the broadcast transaction (requires the platform fee- threading commit; see the DASHSYNC_MIGRATION.md platform pin). SwiftUI screens (UI/DashPay/Contacts/SwiftUI/), styled to the Android dash-wallet DashPay design (dashpay_contact_row.xml et al.): contacts home (card rows, Accept pill + round ignore, golden pending state, Android empty state), add-contact (debounced DPNS search, collision detection, DashPay-key eligibility marking via identityGetKeys mirroring the send path's key predicate), contact profile (Pay CTA, tap-the-header collapsible contact settings, payments history, green accept / ignore pane), notifications (New/Earlier, inline accept), and the Android HSV avatar algorithm (hue = charIndex/36, S 0.3, V 0.6). DPNS names render without the implied ".dash" suffix. Deleted (163 files): the DWDP* item/factory hierarchy, contacts VCs/models/FRC data sources, GlobalSearch, DWDashPayContactsUpdater/ Actions, DWNotificationsProvider/Data/VC/cells, the other-user profile stack, DWDPAmount*View, dead DWFilterHeaderView, and the pay-to-user payment plumbing (paymentInputWithUserItem — a frozen DSIncomingFundsDerivationPath read — plus the performPayToUser chain; the payment-confirm accept-contact checkbox is now honestly hidden). Kept: Items/Protocols headers (type the always-nil payment userItem; fall with the C8 processor rewrite), DWDPAvatarView (current-user surfaces), the invitation flow (out of scope per Row #16). The Contacts/Explore tabs now gate on DWCurrentUserIdentityInfo.hasIdentity — the old DashSync defaultBlockchainIdentity gate hid them from SDK-registered identities. Requires ../platform on local/tx-decode-plus-v4.1-dev (see the platform pin note in DASHSYNC_MIGRATION.md) and an xcframework rebuild. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
QuantumExplorer
added a commit
that referenced
this pull request
Jul 8, 2026
From a deleted-vs-new gap audit of the Row #18 contacts rebuild, restore the four legacy behaviors worth keeping: 1. Un-cap DPNS search (limit 10 → 0 = SDK default 100, the legacy page size); move eligibility checks to lazy per-row onAppear so a large result set doesn't fan out a key query per hit. 2. Enrich the contact-profile payment rows: current-rate fiat, tap through to the standard tx-detail screen (reusing TXDetailVCWrapper via navigationDestination), and the 'direct-to-address payments aren't retained' caption. Non-resolving txs stay non-tappable. 3. Add outgoing 'You sent a contact request to X' notification entries. 4. Add a search-result preview/confirm sheet (avatar, name, framing, collision-appropriate CTA) as the single send/accept surface. Honest limitation: the SDK has no on-chain profile fetch for an arbitrary identity (cache-only reads), so a true stranger shows username + placeholder, not a fetched bio. Deliberately not restored: the pay-confirm accept-contact checkbox and post-payment profile modal (superseded), and the invitation promos (blocked on the not-yet-migrated DashSync invitation flow). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
QuantumExplorer
added a commit
that referenced
this pull request
Jul 9, 2026
… DashSync subsystem Migration Row #18 — the contacts feature (dead at runtime since the post-M6 DashSync freeze) is rebuilt end-to-end on SwiftDashSDK and the entire DashSync implementation is removed in the same change. E2E-verified on testnet against SwiftExampleApp driving the far side: request sent → reciprocated → established → paid both directions. New SDK boundary (Sources/Infrastructure/SwiftDashSDK/Contacts/): - SwiftDashSDKContactsService: SwiftData read model (established = both direction rows, single row = pending; debounced NSManagedObjectContextDidSave refresh), PIN-gated send/accept via DWIdentityAuthorizer + KeychainSigner, ignoreSender (replaces the legacy decline, which was a TODO stub that faked failure), DPNS prefix search + reverse lookup (dpnsGetUsername, base58), contact meta (alias/note/hide via EstablishedContact + flushPersist), notifications read-state on the legacy DWGlobalOptions slot, and the payments projection (see below). - DWIdentityKeyUpgrader: dashwallet registration derives AUTHENTICATION keys only, so identities registered here could not send contact requests. Before the first contact action, one IdentityUpdate adds the missing ENCRYPTION + DECRYPTION keys (ECDSA, MEDIUM, bounds SingleContractDocumentType(DashPay, "contactRequest") — Drive rejects unbound or contract-level bounds). - DashPay background sync (15s six-step pass) start/stop wired into PlatformAddressSyncCoordinator alongside BLAST + shielded. - SDK.enableLogging installed at host init — the app previously ran the whole SDK with Rust diagnostics muted. Payments correctness (found live-testing): - PersistentDashpayPayment rows exist only via the app-pulled projection (PlatformWalletManager.refreshDashPayPayments); the Rust persister never pushes them, and Sent entries are unrecoverable if the app dies before a projection. The service now projects on every sync pass, at most once a minute on snapshot refresh, on profile open, and immediately after every successful send. - WalletSendService.sendToContact: pay-to-contact through the send boundary — spend-auth gate, then the single-shot SDK sendDashPayPayment (derives the DIP-15 address Rust-side), invoked only after the user's explicit Pay tap. Returns the exact network fee of the broadcast transaction (requires the platform fee- threading commit; see the DASHSYNC_MIGRATION.md platform pin). SwiftUI screens (UI/DashPay/Contacts/SwiftUI/), styled to the Android dash-wallet DashPay design (dashpay_contact_row.xml et al.): contacts home (card rows, Accept pill + round ignore, golden pending state, Android empty state), add-contact (debounced DPNS search, collision detection, DashPay-key eligibility marking via identityGetKeys mirroring the send path's key predicate), contact profile (Pay CTA, tap-the-header collapsible contact settings, payments history, green accept / ignore pane), notifications (New/Earlier, inline accept), and the Android HSV avatar algorithm (hue = charIndex/36, S 0.3, V 0.6). DPNS names render without the implied ".dash" suffix. Deleted (163 files): the DWDP* item/factory hierarchy, contacts VCs/models/FRC data sources, GlobalSearch, DWDashPayContactsUpdater/ Actions, DWNotificationsProvider/Data/VC/cells, the other-user profile stack, DWDPAmount*View, dead DWFilterHeaderView, and the pay-to-user payment plumbing (paymentInputWithUserItem — a frozen DSIncomingFundsDerivationPath read — plus the performPayToUser chain; the payment-confirm accept-contact checkbox is now honestly hidden). Kept: Items/Protocols headers (type the always-nil payment userItem; fall with the C8 processor rewrite), DWDPAvatarView (current-user surfaces), the invitation flow (out of scope per Row #16). The Contacts/Explore tabs now gate on DWCurrentUserIdentityInfo.hasIdentity — the old DashSync defaultBlockchainIdentity gate hid them from SDK-registered identities. Requires ../platform on local/tx-decode-plus-v4.1-dev (see the platform pin note in DASHSYNC_MIGRATION.md) and an xcframework rebuild. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
QuantumExplorer
added a commit
that referenced
this pull request
Jul 9, 2026
From a deleted-vs-new gap audit of the Row #18 contacts rebuild, restore the four legacy behaviors worth keeping: 1. Un-cap DPNS search (limit 10 → 0 = SDK default 100, the legacy page size); move eligibility checks to lazy per-row onAppear so a large result set doesn't fan out a key query per hit. 2. Enrich the contact-profile payment rows: current-rate fiat, tap through to the standard tx-detail screen (reusing TXDetailVCWrapper via navigationDestination), and the 'direct-to-address payments aren't retained' caption. Non-resolving txs stay non-tappable. 3. Add outgoing 'You sent a contact request to X' notification entries. 4. Add a search-result preview/confirm sheet (avatar, name, framing, collision-appropriate CTA) as the single send/accept surface. Honest limitation: the SDK has no on-chain profile fetch for an arbitrary identity (cache-only reads), so a true stranger shows username + placeholder, not a fetched bio. Deliberately not restored: the pay-confirm accept-contact checkbox and post-payment profile modal (superseded), and the invitation promos (blocked on the not-yet-migrated DashSync invitation flow). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
QuantumExplorer
added a commit
that referenced
this pull request
Jul 9, 2026
…subsystem (#787) * fix(tx): pass ManagedPlatformWallet to the core TransactionBuilder calls setFunding/addInputs/buildSigned take ManagedPlatformWallet on every published platform ref (v4.1-dev's #3970 API); the ManagedCoreWallet overloads the call sites were written against never shipped. The platform wallet is already in scope; ManagedCoreWallet stays for broadcastTransaction only. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(contacts)!: rebuild DashPay contacts on SwiftDashSDK, delete the DashSync subsystem Migration Row #18 — the contacts feature (dead at runtime since the post-M6 DashSync freeze) is rebuilt end-to-end on SwiftDashSDK and the entire DashSync implementation is removed in the same change. E2E-verified on testnet against SwiftExampleApp driving the far side: request sent → reciprocated → established → paid both directions. New SDK boundary (Sources/Infrastructure/SwiftDashSDK/Contacts/): - SwiftDashSDKContactsService: SwiftData read model (established = both direction rows, single row = pending; debounced NSManagedObjectContextDidSave refresh), PIN-gated send/accept via DWIdentityAuthorizer + KeychainSigner, ignoreSender (replaces the legacy decline, which was a TODO stub that faked failure), DPNS prefix search + reverse lookup (dpnsGetUsername, base58), contact meta (alias/note/hide via EstablishedContact + flushPersist), notifications read-state on the legacy DWGlobalOptions slot, and the payments projection (see below). - DWIdentityKeyUpgrader: dashwallet registration derives AUTHENTICATION keys only, so identities registered here could not send contact requests. Before the first contact action, one IdentityUpdate adds the missing ENCRYPTION + DECRYPTION keys (ECDSA, MEDIUM, bounds SingleContractDocumentType(DashPay, "contactRequest") — Drive rejects unbound or contract-level bounds). - DashPay background sync (15s six-step pass) start/stop wired into PlatformAddressSyncCoordinator alongside BLAST + shielded. - SDK.enableLogging installed at host init — the app previously ran the whole SDK with Rust diagnostics muted. Payments correctness (found live-testing): - PersistentDashpayPayment rows exist only via the app-pulled projection (PlatformWalletManager.refreshDashPayPayments); the Rust persister never pushes them, and Sent entries are unrecoverable if the app dies before a projection. The service now projects on every sync pass, at most once a minute on snapshot refresh, on profile open, and immediately after every successful send. - WalletSendService.sendToContact: pay-to-contact through the send boundary — spend-auth gate, then the single-shot SDK sendDashPayPayment (derives the DIP-15 address Rust-side), invoked only after the user's explicit Pay tap. Returns the exact network fee of the broadcast transaction (requires the platform fee- threading commit; see the DASHSYNC_MIGRATION.md platform pin). SwiftUI screens (UI/DashPay/Contacts/SwiftUI/), styled to the Android dash-wallet DashPay design (dashpay_contact_row.xml et al.): contacts home (card rows, Accept pill + round ignore, golden pending state, Android empty state), add-contact (debounced DPNS search, collision detection, DashPay-key eligibility marking via identityGetKeys mirroring the send path's key predicate), contact profile (Pay CTA, tap-the-header collapsible contact settings, payments history, green accept / ignore pane), notifications (New/Earlier, inline accept), and the Android HSV avatar algorithm (hue = charIndex/36, S 0.3, V 0.6). DPNS names render without the implied ".dash" suffix. Deleted (163 files): the DWDP* item/factory hierarchy, contacts VCs/models/FRC data sources, GlobalSearch, DWDashPayContactsUpdater/ Actions, DWNotificationsProvider/Data/VC/cells, the other-user profile stack, DWDPAmount*View, dead DWFilterHeaderView, and the pay-to-user payment plumbing (paymentInputWithUserItem — a frozen DSIncomingFundsDerivationPath read — plus the performPayToUser chain; the payment-confirm accept-contact checkbox is now honestly hidden). Kept: Items/Protocols headers (type the always-nil payment userItem; fall with the C8 processor rewrite), DWDPAvatarView (current-user surfaces), the invitation flow (out of scope per Row #16). The Contacts/Explore tabs now gate on DWCurrentUserIdentityInfo.hasIdentity — the old DashSync defaultBlockchainIdentity gate hid them from SDK-registered identities. Requires ../platform on local/tx-decode-plus-v4.1-dev (see the platform pin note in DASHSYNC_MIGRATION.md) and an xcframework rebuild. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(dashpay): restore four legacy contact affordances on SwiftDashSDK From a deleted-vs-new gap audit of the Row #18 contacts rebuild, restore the four legacy behaviors worth keeping: 1. Un-cap DPNS search (limit 10 → 0 = SDK default 100, the legacy page size); move eligibility checks to lazy per-row onAppear so a large result set doesn't fan out a key query per hit. 2. Enrich the contact-profile payment rows: current-rate fiat, tap through to the standard tx-detail screen (reusing TXDetailVCWrapper via navigationDestination), and the 'direct-to-address payments aren't retained' caption. Non-resolving txs stay non-tappable. 3. Add outgoing 'You sent a contact request to X' notification entries. 4. Add a search-result preview/confirm sheet (avatar, name, framing, collision-appropriate CTA) as the single send/accept surface. Honest limitation: the SDK has no on-chain profile fetch for an arbitrary identity (cache-only reads), so a true stranger shows username + placeholder, not a fetched bio. Deliberately not restored: the pay-confirm accept-contact checkbox and post-payment profile modal (superseded), and the invitation promos (blocked on the not-yet-migrated DashSync invitation flow). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(home): testnet faucet shortcut, default over Spend on testnet New 'Request 1 tDash' shortcut (testnet only): copies the wallet's receive address and opens the testnet faucet in-app, mirroring the Explore screen's get-test-dash flow. On testnet it replaces Spend as the default fourth shortcut and joins the customization list; a saved faucet shortcut degrades to Spend while on mainnet (config untouched). The request itself stays in the web page — the faucet API requires its anti-bot challenge token, which only the page can produce (verified: bare POST to /api/core-faucet returns 400 'Captcha token required'). Also fixes the Explore faucet link: the faucet no longer answers on port 80, so the http:// URL opened nothing. The new enum case is appended last — raw values persist in DWGlobalOptions.shortcuts. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * style(home): shorten the faucet shortcut label to '1 tDash' Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(home): faucet shortcut drives the request in-app, web only as fallback The '1 tDash' shortcut now calls the SDK's TestnetFaucet client (promoted from SwiftExampleApp — platform 5f53767be7): solve the faucet's soft cap.js proof-of-work on-device, POST the receive address to /api/core-faucet, show the result in a HUD. No web page on the happy path. Rate limit or any failure falls back to the previous behavior: copy the address, open the web faucet in-app, log why. Mechanism live-verified against faucet.thepasta.org: challenge -> solve -> redeem -> 200, 1 tDash delivered (txid 395eeb08...). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(dashpay): enforce the spending limit and reject overflowing amounts on pay-to-contact Review fixes (llbartekll): - sendToContact now passes spendAmount to authorizeSend, engaging the C7.4 biometric spending limit; without it the gate was non-monetary and Face ID alone authorized a contact payment of any size. - PayContactSheet validates the entered amount in Decimal space before the UInt64 conversion; NSDecimalNumber.uint64Value wraps modulo 2^64, so 2^64+1 duffs aliased to 1 duff, passed the range check, and broadcast the wrong amount while the success screen echoed the typed text. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
llbartekll
added a commit
that referenced
this pull request
Jul 9, 2026
…etailCellView With the userItem plumbing gone, the DWDP item protocol layer lost its last consumers. Deleted: the 12 protocol/associated-data headers under UI/DashPay/Items/Protocols (7 were orphaned since the #787 contacts teardown; DWDPBasicUserItem/DWDPBasicItem/DWDPBlockchainIdentityBackedItem fell with the plumbing — DWDPBasicUserItem itself was DS-tainted via DSFriendRequestEntity/DSBlockchainIdentity returns), the ObjC DWTitleDetailCellView.{h,m} (zero code/xib consumers — the confirm sheet renders through the Swift TitleValueCell), and its sole dependent DWDPSmallContactView.{h,m}. DWTitleDetailItem drops the userItem member and the _User style; DWTitleDetailCellModel drops the user initializer. Bridging header and pbxproj (38 lines; DWTitleDetailCellView.m had build-file entries in both targets) scrubbed; plutil -lint OK. Kept deliberately: DWDPAvatarView (live on Home/invites/username/profile surfaces; its blockchainIdentity property is Row #18 scope). Co-Authored-By: Claude Fable 5 <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.
No description provided.