Skip to content

feat(uploads): live progress for external-signer flow + wagmi fixes - #66

Merged
Nic-dorman merged 5 commits into
mainfrom
feat/external-signer-progress-events-gui
Apr 30, 2026
Merged

feat(uploads): live progress for external-signer flow + wagmi fixes#66
Nic-dorman merged 5 commits into
mainfrom
feat/external-signer-progress-events-gui

Conversation

@Nic-dorman

@Nic-dorman Nic-dorman commented Apr 29, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Wires the WalletConnect / external-signer flow into the same upload-progress Tauri-event pipeline feat(uploads/downloads): live progress bar driven by ant-core events #65 introduced for the wallet-flow + downloads. start_upload / confirm_upload / confirm_upload_merkle all spawn spawn_upload_progress_forwarder and pass it into ant-core's _with_progress methods (now in ant-core-v0.2.2).
  • Closes the listener-routing gap for opaque quote-... transfer ids by introducing a _transferIdToRowId map in the files store, populated before start_upload is invoked so quote-phase events route from the very first event.
  • Picks up two wallet bugs that surfaced during Sepolia testing: chain auto-switch and a corrected EIP-1559 fee config.
  • A few UX polish items (showsProgressBar widening, per-stage percent in label, status badge truncation).

What changed

Rust (src-tauri/src/autonomi_ops.rs)

start_upload          → file_prepare_upload_with_progress(path, Visibility::Private, Some(tx))
confirm_upload        → finalize_upload_with_progress(prepared, &tx_hash_map, Some(tx))
confirm_upload_merkle → finalize_upload_merkle_with_progress(prepared, hash, Some(tx))

All three spawn spawn_upload_progress_forwarder(app, upload_id) (already on main from #65) so events route via the same Tauri upload-progress channel.

Frontend

  • stores/files.ts_transferIdToRowId: Record<string, number> populated by getUploadQuote(path, transferRowId?) before invoke('start_upload'). Listener falls back to Number(transfer_id) so the wallet/download paths (which stringify the row id) keep working unchanged.
  • pages/files.vueshowsProgressBar() now returns true for quoting / paying too. stageDetail() returns a per-stage percent ("Storing · 67%") instead of a fraction.
  • components/StatusBadge.vuemax-w-xs truncate + title so long error messages don't widen the table.

utils/payment.ts

  • ensureActiveChain(wagmiConfig) calls switchChain before each writeContract if the wallet's current chainId doesn't match getActiveChainId(). This is the same chain-mismatch issue reported against the 0.6.7 release ("current chain id 1 does not match target chain id 42161 - Arbitrum One") — surfaces whenever MetaMask is sitting on a different chain than the manifest expects.
  • All three writeContract sites now pass both maxFeePerGas: 1_000_000_000n and maxPriorityFeePerGas: 100_000_000n. An earlier fix that set only the priority fee tripped EIP-1559's maxFee >= maxPriority invariant on Arbitrum's tiny base fees and surfaced as a generic "User rejected the request" wrapper.

Test plan

  • cargo check --all-targets clean against ant-core-v0.2.2 (just-merged via chore(deps): bump ant-core 0.2.0 -> 0.2.2 #67)
  • cargo clippy --all-targets -- -D warnings clean
  • cargo fmt --check clean
  • End-to-end Sepolia upload (devnet-sepolia rig + MetaMask Mobile via WalletConnect, funded test wallet). 9-chunk file completes cleanly; bar climbs 0→50% during quoting, then 50→100% during storage; row settles to Complete.
  • Reviewer: confirm the bar UX feels right under your network conditions

Nic-dorman and others added 5 commits April 30, 2026 10:37
…external-signer

Builds on top of #65 (direct-path progress wiring) to also drive a live
progress bar through the WalletConnect / external-signer flow, plus a
small grab-bag of fixes that surfaced during end-to-end Sepolia testing.

The three external-signer Tauri commands now spawn the same forwarder
PR #65 introduced and pass it into ant-core's new `_with_progress`
upstream methods:

  start_upload          → file_prepare_upload_with_progress
  confirm_upload        → finalize_upload_with_progress
  confirm_upload_merkle → finalize_upload_merkle_with_progress

ant-core dep is pinned to the upstream PR's branch
(`feat/external-signer-progress-events`) until that lands and a tag
ships. Swap the dep back to a tagged `ant-core-vX.Y.Z` once #68 is
merged + tagged.

External-signer's transfer_id is the opaque `quote-...` string returned
by `start_upload`, not the row id. The progress listener gains a
`_transferIdToRowId` map, populated as soon as `getUploadQuote` knows
the id (BEFORE invoking start_upload, so quote-phase events route from
the very first event). The wallet/download paths still use `String(id)`
and fall through to the numeric parse — both flows share one listener.

- `showsProgressBar` widened to render during `quoting` / `paying` too,
  not just `uploading`. The bar otherwise vanished during the wallet
  popup and the bulk of the work on the external-signer path.
- `stageDetail()` switched to per-stage percent ("Storing · 67%") instead
  of fractions ("Storing · 6/9"). Bar = global progress, label = local.
- `StatusBadge` gets `max-w-xs truncate` + a `title` tooltip so long
  failure messages don't blow the table width.

- **V2-236** chain auto-switch — `ensureActiveChain()` calls
  `switchChain` before `writeContract` so the wallet is always on the
  target chain. Without it, a wallet on Arbitrum One signing for an
  Arbitrum Sepolia tx blew up with a chain-mismatch error and no clear
  recovery in the UI.
- **V2-231** EIP-1559 fee invariant — override BOTH `maxFeePerGas` and
  `maxPriorityFeePerGas` explicitly (1 gwei / 0.1 gwei). viem's
  partial auto-estimation produced an invalid pair on Arbitrum's tiny
  base fees, surfacing as either a base-fee race or a "User rejected"
  wrapper around the underlying invariant violation. Three sites
  (payForQuotes, payForMerkleTree, approve in ensureAllowance).

End-to-end on a Sepolia-EVM devnet (`start-devnet-sepolia` from
ant-client + MetaMask Mobile via WalletConnect, funded Sepolia wallet):

- 9-chunk file, full external-signer flow: quote → MM popup → store
- Bar climbs 0→50% during quoting (per-chunk ChunkQuoted), pauses at
  50% during the MM popup, climbs 50→100% during storage.
- Tx hash confirmed on chain, `External-signer upload finalized` logged
- 21/21 vitest pass, cargo check clean against the branch ant-core dep

Path-dep to upstream branch will fail any CI that pulls a registry-only
ant-core. Hold until #68 lands, then bump the dep to the new tag and
unmark draft.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…umn layout

Layout changes (pages/files.vue):
- Status column moved one to the left in both upload and download tables.
- File name cell becomes the wider one: filename on top, progress bar below
  (only when active). Bar gets a min-w-[8rem] so flex-1 segments don't
  collapse to invisible widths in narrow rows.
- Status cell stacks the badge on top with the stage detail line below it,
  so badge + sub-text track together visually.

Progress bar (components/ProgressLine.vue + new BarSegment.vue + PayDot.vue):
- Upload bar is now segmented [quote] · [pay-dot] · [store], conveying the
  three-phase shape of the external-signer flow at a glance. Wallet-flow
  and downloads use the same component but the dot stays solid (wallet)
  or the bar collapses to a single fill (download).
- Bar fill is now stage-driven, not status-driven. Wallet-flow JS pre-flips
  status='uploading' before any quoting starts; the old logic took that
  literally and rendered the left segment full + dot solid before any work
  was done. New logic prefers the live `stage` from ant-core's events and
  uses status only as a "we're past quoting" fallback (paying / complete).
- PayDot's empty state uses bg-autonomi-surface (same as the bar tracks)
  instead of a transparent bordered ring, for tighter visual cohesion.

Status label (pages/files.vue + components/StatusBadge.vue):
- statusLabel() now consults `stage` when the outer status disagrees with
  the inner phase. Wallet-flow uploads under stage='quoting' now show
  "Quoting" instead of "Uploading"; downloads under stage='resolving'
  show "Resolving datamap" instead of "Downloading". Badge + sub-text
  stay in sync.
- StatusBadge: non-error labels render at natural width with
  whitespace-nowrap (no truncate, no max-w), so the column auto-sizes
  tight to its widest live label. Error labels keep `max-w-xs truncate`
  so a viem stacktrace can't blow the column out.
- New badge entries for "Encrypting…" and "Resolving datamap".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…reloads

Previously the runtime FileEntry tracked gas_cost (rendered as a small
"+ X gas" line under cost in the table) but the persisted UploadHistoryEntry
shape didn't carry it. On app reload / Files-page refresh, every completed
upload reloaded with cost intact but gas_cost dropped — the second line
silently vanished.

Adds optional gas_cost?: string | null on both the TS UploadHistoryEntry
and the Rust struct (with #[serde(default)] for backwards compat with
existing history files). loadHistory() and persistHistory() round-trip
the field. Legacy entries written before this change remain valid and
just render without the gas line, same as before.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…istory

V2-233: each settled (failed / complete / downloaded) row now reveals a
hover affordance on the right — `✕` for remove. Wires to the existing
`removeEntry()` store action.

V2-234: failed upload rows also show a `↻ Retry` button. Reuses
`entry.path` so the user doesn't re-pick the file from disk; the new
`retryUpload()` store action clears stale per-attempt fields (error,
progress, stage*, address, datamap, costs, gas), flips status to
`queued_for_upload`, and lets the page scheduler re-run
`startRealUpload` (fresh quote + fresh wagmi sign).

V2-232: bulk "Clear history" moves out of the Files page header and
into Settings as a confirmation-gated action. The per-row × covers the
common case of trimming one entry; bulk wipe is one click further away
to prevent accidental loss. The new Settings card shows the count of
settled entries that would be removed and is disabled when there's
nothing to clear.

Companion rename surfaced earlier in the session: external-signer's
`paying` status now renders as "Awaiting approval" instead of "Paying"
— more accurate while wagmi is awaiting the wallet signature, and
unambiguous since the wallet flow never enters this state.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Nic-dorman
Nic-dorman force-pushed the feat/external-signer-progress-events-gui branch from 4ae63ee to 8ed72c2 Compare April 30, 2026 09:39
@Nic-dorman Nic-dorman changed the title WIP: feat(uploads): live progress for external-signer flow + wagmi fixes (depends on ant-client#68) feat(uploads): live progress for external-signer flow + wagmi fixes Apr 30, 2026
@Nic-dorman
Nic-dorman marked this pull request as ready for review April 30, 2026 09:41
@Nic-dorman
Nic-dorman merged commit a39e3c1 into main Apr 30, 2026
4 checks passed
@Nic-dorman
Nic-dorman deleted the feat/external-signer-progress-events-gui branch April 30, 2026 11:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant