Repository navigation
feat(analytics): time each phase of a Coinbase add-money purchase - #1935
Merged
Merged
Conversation
Seven optional duration properties split a Coinbase add-money purchase
into Order, Payment, Coinbase, Deposit, Swap and Credit phases plus a
total, so a dashboard can show which phase slowed down. The event
description names each property's start and end moment in
platform-neutral words so iOS can time the same spans.
Token Purchase With {method}, Onramp: {step} and Create Account Payment
drop the "part 2 decides whether iOS sends it" wording: iOS sends all
three.
AddMoneyTimer holds a monotonic mark per moment and turns them into the Add Money phase durations; the clock is injectable so tests drive it with TestTimeSource. SwapViewModel starts it when the amount is confirmed and reads it on every Coinbase Add Money send, success or failure. Two moments had no outlet. The webview's payment_authorized event now reaches CoinbaseOnRampController, which emits it and polling_success on a non-conflated milestones flow; the state flow can skip Completed when the handler resets right after. UsdcDepositSweep emits UsdcSeen and Swapped on its own milestones flow. It is a singleton the session also starts, so the view model listens to whichever sweep runs; the timer ignores sweep moments before polling_success so a leftover-balance sweep can't count.
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.
Adds seven optional duration properties (ms) to the
Add Moneyevent so a Mixpanel dashboard can show which phase of a Coinbase purchase got slower since Solana's Alpenglow upgrade. They're sent only when Method is Coinbase. On a failure, the phases that finished are sent with Total Time and the rest are absent.onramp_api.payment_authorizedevent (includes the user's own time on the pay sheet)onramp_api.payment_authorizedonramp_api.polling_successeventonramp_api.polling_successAdd Moneyis sent, success or failureiOS needs to match one rule that isn't obvious from the table: when the user is sent to verify a phone number or email first, both clocks restart when they come back and confirm the amount again. Android re-dispatches
OnAmountConfirmedafter verification, so this falls out of where the timer starts. The rule is in the event description.Android sender
AddMoneyTimer(shared/tokens, commonMain) holds one monotonic mark per moment and computes the phases. ItsTimeSourceis injectable, and tests drive it withTestTimeSource.SwapViewModelstarts it on amount confirm and reads it in one helper that everyAdd Moneyresult send now goes through.Two moments had no outlet before:
payment_authorizedonly paused the webview watchdog. It now reachesCoinbaseOnRampController, which emits it andpolling_successon amilestonesSharedFlow. It isn't a newCoinbaseOnRampStatebecause the handler callsreset()right afterCompleted, and the conflated StateFlow can skip it.UsdcDepositSweepemitsUsdcSeenandSwappedon its ownmilestonesflow. It's a singleton that the session'sDepositDelegatealso starts, so a call from the view model can be a no-op while a session sweep does the work. The view model listens to whichever sweep runs. The timer ignores sweep moments beforepolling_success, so a sweep of leftover USDC can't count as the deposit.The generated
AddMoneyEvents.resultkeeps its four leading parameters, so existing callers compile unchanged.AddMoneyEventsTest.resultIsTheEventNamedAddMoneyis untouched.SwapViewModelErrorTestasserts the whole event for a full Coinbase success, a delivery failure (Order/Payment/Coinbase/Total only), and a Phantom deposit with no phase properties.The controller's
onPaymentAuthorizedonly has a negative test (no emit outside a payment). Getting toPayingthere needs the JWT and order stubs.CoinbaseOnRampEventHandlerTestcovers the webview event reaching the callback.Catalogue descriptions
Token Purchase With {method},Onramp: {step}andCreate Account Paymentdrop the "Android only; part 2 decides whether iOS sends it" wording, because iOS sends all three (a parallel iOS PR is wiring them). Create Account Payment now says it's the account-creation payment, distinct from Create Account at registration. Drift notes are unchanged.Follow-up
The direct launchpad-token buy through Coinbase is out of scope.
addMoneyMethodis null when the mint isn't USDF, so that path sends noAdd Moneyand no phase times.