-
Notifications
You must be signed in to change notification settings - Fork 25
fix(wallet): say what actually happens after a send we could not confirm #1125
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from 1 commit
e467a1d
7d70df7
3a1112c
a08edba
6270146
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -144,19 +144,38 @@ final class PreparedStandardSend: NSObject { | |
| txidWire: Data(txHash.reversed()), address: address, amount: amount, fee: fee) | ||
|
|
||
| case .rejected(_, let reason): | ||
| // Nothing reached the network, so the money is provably still | ||
| // here — say that, because "wasn't sent" alone reads as a loss. | ||
| let error = WalletSendService.makeError( | ||
| code: .broadcastRejected, | ||
| description: "The transaction wasn't sent. You can try again. \(reason)" | ||
| description: NSLocalizedString( | ||
| "The transaction wasn't sent, so nothing left your wallet. You can try again.", | ||
| comment: "Send failed before any bytes reached the network"), | ||
| diagnostic: reason | ||
| ) | ||
| claimLock.lock() | ||
| broadcastState = .ready | ||
| claimLock.unlock() | ||
| throw error | ||
|
|
||
| case .unknown(_, let reason): | ||
| // The old copy told the user to "wait for wallet synchronization" | ||
| // without saying that the wallet is the thing doing the waiting — | ||
| // and it appended the SDK's internal reason, so the dialog ended | ||
| // in "SPV broadcast saw no acceptance signal before dash-spv's | ||
| // acceptance timeout". Neither was actionable, and neither was | ||
| // localized, so a customer on a non-English device got a wall of | ||
| // English (support ticket 32189). | ||
| // | ||
| // The retry promise is now true rather than aspirational: the | ||
| // send is re-registered for rebroadcast at every launch, so it | ||
| // survives closing the app. | ||
| let error = WalletSendService.makeError( | ||
| code: .broadcastUnknown, | ||
| description: "We couldn't confirm whether the transaction was accepted. Don't send it again; wait for wallet synchronization. \(reason)" | ||
| description: NSLocalizedString( | ||
| "We couldn't confirm the transaction reached the network. Don't send it again — the wallet keeps trying on its own, and your balance will update as soon as it goes through.", | ||
| comment: "Send dispatched but no network acceptance signal arrived"), | ||
| diagnostic: reason | ||
| ) | ||
| claimLock.lock() | ||
| broadcastState = .unknown(error) | ||
|
|
@@ -727,11 +746,25 @@ private extension WalletSendService { | |
| comment: "DashPay Contacts")) | ||
| } | ||
|
|
||
| static func makeError(code: ErrorCode, description: String) -> NSError { | ||
| NSError( | ||
| /// `userInfo` key carrying the SDK's own explanation of a broadcast | ||
| /// outcome. Deliberately not `NSLocalizedDescriptionKey`: it is | ||
| /// engineer-facing text and must never reach a dialog, but support | ||
| /// still wants it on the error that gets logged. | ||
| static let diagnosticKey = "org.dashfoundation.dash.send.diagnostic" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 Suggestion: Expose diagnosticKey at module scope for cross-file diagnostics
source: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Resolved (re-reviewed at There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Resolved (re-reviewed at There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Resolved (re-reviewed at |
||
|
|
||
| static func makeError( | ||
| code: ErrorCode, | ||
| description: String, | ||
| diagnostic: String? = nil | ||
| ) -> NSError { | ||
| var userInfo: [String: Any] = [NSLocalizedDescriptionKey: description] | ||
| if let diagnostic, !diagnostic.isEmpty { | ||
| userInfo[diagnosticKey] = diagnostic | ||
| } | ||
| return NSError( | ||
| domain: errorDomain, | ||
| code: code.rawValue, | ||
| userInfo: [NSLocalizedDescriptionKey: description] | ||
| userInfo: userInfo | ||
| ) | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟡 Suggestion: Remove the remaining claim that retries survive app closure
This comment says the send is re-registered at every launch and survives closing the app. That contradicts the user-facing copy and the current SDK behavior described in the PR: dash-spv only continues retrying while the wallet remains open, and launch-time re-registration depends on platform#4659, which is not part of this head. Keeping the comment can mislead a future maintainer into removing the necessary open-app qualifier or relying on behavior that is not shipped.
source:
gpt-6-astra(phase2-reviewer: general)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in
a08edba8b. You are right that this was the dangerous half of the leftover: a comment contradicting the string next to it is how the qualifier gets deleted later by someone who trusts the comment, and the misleading promise lands back in front of users.The comment now states what the shipped SDK does — retries continue while the wallet is open — and says explicitly that launch-time re-registration is dashpay/platform#4659 and not in this head, pointing at
BroadcastOutcomeCopy.unknownfor when the qualifier can be dropped.🤖 Reviewed with Claude Code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resolved (re-reviewed at
a08edba8): The misleading comment has been replaced with wording that limits retry behavior to while the wallet remains open and explicitly identifies launch-time re-registration as a future platform change.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resolved (re-reviewed at
62701467): The misleading launch-time retry claim and the suggestion that retries survive app closure have been removed; the surrounding comment now documents that the shipped SDK retries only while the wallet remains open.