Repository navigation
Feat/27 deploy flow - #112
Conversation
TOMOKI977
left a comment
There was a problem hiding this comment.
Nice work on the split, and thanks for addressing the #109 review so carefully. The blockers from that round are resolved:
- The demo is labelled everywhere:
isDemois required on the gateway, the app shows "Demo deploy only", and there's no fake hash or explorer link. WalletPortnow only signs and returns the signed XDR, matching the relay.PreparationExpiredre-prepares on retry.- The explorer URL uses
stellarExpertTxUrl. - Disposal is guarded with
_Cancelled.
The controller's resume logic and the tests around it are solid.
I'm requesting changes for one thing only:
A wallet that never answers connect() traps the user. _wallet.connect() runs inside the preparing step without a timeout (deploy_flow_controller.dart:189). busy only lets the user leave during awaitingSignature (deploy_flow.dart:109-111), so the Close button is hidden and PopScope blocks back, and the sheet is isDismissible: false with enableDrag: false (deploy_sheet.dart:20-21). With a real wallet (#113), an ignored or stuck connect popup leaves the restart as the only way out. Either put the same timeout on connect() that signTransaction has, or let the user close while the wallet connect is pending. Please add a test with a connect() that never completes, like the one you have for signing.
Not blocking, but worth keeping in mind for #18/#96:
retry()decides what to discard by error kind, not by step (deploy_flow_controller.dart:169-176). Perapi.md:163,169,set_agent_walletcan fail withTransactionFailed/AuthorizationExpiredwhile the agent stays registered. If the realactivatemaps those to the same kinds, Retry would drop_registrationand register a second agent.- When the signature times out, the original
signTransactionfuture keeps running, so a retry can open a second wallet prompt. - The permanent submit rejections (
EnvelopeMismatch,InvalidSignedEnvelope,PreparationNotFound,SubmissionInProgress) have no error kind, so they'd fall into "retry is safe" and resend the same payload. activate()has no second signature forset_agent_wallet(api.md:157), so the claim indeploy_gateway.dartthat the real gateway drops in "without touching the flow" won't hold.- Copy is split between
deploy_copy.dartand literals in three organisms. The step-timeout message is built in the controller and prints "null s" when there's no timeout (deploy_flow_controller.dart:320). User-facing text cites "#18". - The agent ID and transaction rows are built twice (flow view and success view), and
isDemois passed separately fromresult.isDemo. - The non-demo publish path in
DeploySheet._publishhas no test. - The title "Feat/27 deploy flow" isn't a conventional commit title. Suggested:
feat(flutter): deploy flow UI with stepper and error recovery, plus thearea: frontend/type: featlabels.
|
@Pericena Heads-up: CI changes when #114 (Serverpod 4.0.4) merges. Once it lands on
Specific to this PR: #111 was squash-merged, so please rebase onto |
Part B of the #109 split. Refs #27: the testnet end-to-end criterion waits for the deploy endpoint (#18) and the relay (#96). - DeployFlow + DeployFlowController: preparing -> waiting for signature -> registering on-chain -> activating -> live. Never runs twice, resumes from the failed step, keeps the prepared and signed transaction across a lost response, verifies every backend answer, and stops if the flow is closed mid-run. - Presentational widgets: DeployStepper, phase card, error panel and success, with skeletons until values arrive. - Errors with a recovery action and no reload: signature rejected, transaction failed, backend error, plus wallet unavailable, wrong network, account changed, connection lost/timeout, invalid response, expired preparation (prepares again) and a wallet that never answers (times out; the sheet can be closed while the wallet prompt is open). Review fixes: - The demo gateway is labelled: a banner says nothing is registered on Stellar, and the result reads "Demo deploy only" with no explorer link, no agent page and no made-up hash. Demo agents are not listed. - WalletPort.signTransaction only signs and returns the signed XDR; the server submits (API contract #77, Decision A). MockWallet returns a marked signed placeholder instead of a hash. - Real agents start at a 0.0 rating; explorer links use stellarExpertTxUrl; the unused SuccessPanel, DeployProgressView and AppScope.ids are removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review of #112. The deploy flow connected to the wallet inside the preparing step with no limit, and the sheet could not be closed then, so a stuck connect popup trapped the user. - connect() gets the same wallet timeout as signTransaction(), and "No answer from your wallet" offers a retry. - The flow can be closed while any wallet prompt (connect or sign) is open; server steps stay bounded by the step timeout. - The timeout detail no longer prints "null s" without a step timeout, and user-facing text no longer cites issue numbers. Test: a connect that never completes times out, nothing is prepared, and the user can close the flow while waiting. 122 passing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Dart 3.12 (Serverpod 4 toolchain on main) flags prefer_initializing_formals for private fields. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5862f38 to
bd73747
Compare
Deploying puls3 with
|
| Latest commit: |
4e9f325
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://c77db044.puls3-4lw.pages.dev |
| Branch Preview URL: | https://feat-27-deploy-flow.puls3-4lw.pages.dev |
|
Thanks! Done:
The other non-blocking notes (retry by step, superseded signature futures, permanent submit rejections, set_agent_wallet signature) will go with #18/#96. |
TOMOKI977
left a comment
There was a problem hiding this comment.
Approved. The blocker is resolved:
_waitForWallet()puts the same timeout onconnect()andsignTransaction(), andisWaitingForWalletlets the user close the flow during either prompt.- The
finallynotify is guarded by_disposed, so closing mid-prompt is safe. - The new test (a connect that never answers, close while waiting,
walletTimeoutshown, nothing prepared) covers exactly the case. - I checked the rebase with
range-diff: only the Serverpod 4.0.4 bump, the fix and the style commit. Nothing else changed.
Thanks for the "null s" fix and for removing the issue numbers from the copy. The deferred notes for #18/#96 sound good.
I'll update the branch with main and squash-merge once CI is green.
Refs #25. Built on the deploy flow (#112). The real-wallet acceptance on Testnet (screenshot) and the server relay (#96/#18) are pending. - WalletPort keeps one signing boundary: connect, disconnect, address, network, signTransaction (returns the signed XDR, the server submits) and signAuthEntry. Typed errors: rejected, not installed, locked/ unavailable, wrong network, account changed, invalid payload. - FreighterWallet over a small JS bridge (freighter-api 6.0.1). Before any prompt it checks the payload (#69): Testnet passphrase, no fee-bump envelopes, no trailing bytes, auth entries with a non-zero expiration and address credentials only. After signing it checks the account did not change. - MockWallet for tests and the demo console (--dart-define=WALLET=mock); Freighter is the default on the web. - Wallet sheet (S09): disconnected, connecting, connected (Testnet badge, copyable address, disconnect), cancelled, wrong network, not installed (install link), locked, with a retry in every error. - Demo flows (deploy, hire) sign a harmless, never-submitted Testnet envelope so a real wallet shows its prompt; they stay labelled as demos. Wallet errors show human messages. Tests: 19 for the Freighter adapter checks, 11 for the connection states, chip and phone layout. 151 passing, analyze clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review of #113. - WalletController.connect() times out (2 minutes) with WalletTimedOut, so an ignored, blocked or stuck Freighter popup never traps the deploy flow, the hire sheet or the wallet sheet. The deploy flow also times out its reconnect before re-signing and can be closed while any wallet prompt is open (from #112). - Disconnecting during a pending connect stays disconnected instead of reconnecting when the prompt settles. - The Freighter bridge maps only "rejected:" to a rejection; any other error is WalletUnavailable with a log line (no payload data), not "you rejected". - An unknown --dart-define=WALLET value fails at startup instead of silently using the mock wallet. - Wallet sheet uses Puls3Breakpoints.narrowGutter; one shared waiting bar; README lists signAuthEntry and the timeout. Tests: two Freighter tests now await the future before checking state, so they can fail; new tests for a connect that never answers, disconnect during connect, an account switch while signing, and the timed-out panel. 165 passing, analyze clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #27. Part B of the #109 split; supersedes #109.
Missing for #27: testnet end to end with GIF and tx hash. It needs the deploy endpoint (#18) and the relay (#96). Wiring them means a
DeployGatewayimplementation over the generated client, plus theset_agent_walletsignature,draftIdand session polling from api.md.What it does
DeployFlow+DeployFlowController: preparing → waiting for signature → registering on-chain → activating → live. Never runs twice, resumes from the failed step, keeps the prepared and signed transaction across a lost response, verifies backend answers, stops if closed mid-run.DeployFlowtakes anAgentDraftonly, no dependency on the Studio form.Review fixes from #109
WalletPort.signTransactionsigns and returns the signed XDR; the server submits.MockWalletreturns a marked signed placeholder, not a hash.stellarExpertTxUrl; unusedSuccessPanel,DeployProgressView,AppScope.idsremoved.Tests
Every progress and error state with
MockWalletand a fake client, plus the review fixes (demo labelling, signed envelope, expired preparation, wallet timeout, cancellation).flutter analyze: 0 issues ·flutter test: 121/121Stacked on the theme and shell PR (part A): base is
feat/flutter-theme-shellso the diff shows only the deploy flow. I'll retarget tomainafter A merges.