User Details
- User Since
- Jan 17 2025, 05:34 (82 w, 4 d)
Fri, Aug 14
Abandoning after discussion.
Sat, Aug 8
Fri, Jul 31
Fixed as proposed: a manual row selection now releases the deep-link hold (handleManualSelectOffer clears the outpoint ref before setSelectedIndex), so subsequent refreshes follow the user's choice. Fair catch on the interaction — this was a consequence of moving the hold to outpoint identity last round: the old boolean merely skipped auto-select on refresh (so a manual pick happened to survive), while the identity hold actively re-resolves the held offer, which made "manual selection supersedes the link" need to be explicit. It now is, with a comment stating the rule. Couldn't test the full click-then-refresh sequence (the harness can't drive a mid-session refetch), but the row-click path itself is exercised by the existing multi-offer tests.
All four addressed:
Fixed: the blacklist answer is now bound to the token it was fetched for. A blacklistCheckedForTokenId ref is stamped with the fetch closure's captured tokenId at both set-sites (including the error-assume-false path), and the deep-link gate requires it to match the rendered tokenId — a mismatched answer reads as still-loading, and the effect re-evaluates when the current token's own answer arrives (isBlacklisted is a dependency). This closes the reused-component window where /token/b's deep link could apply against /token/a's stale isBlacklisted === false, with appliedDeepLinkKey then blocking re-evaluation. Couldn't add an automated test — the harness mounts fresh per test and can't drive an in-place route change — but the existing blacklist-refusal test covers the gate's normal path.
Four fixed, two declined with reasons — plus two hardenings from my own pass that the reviewed diff predated (deep-link selection skips the wallet's own offers, with a maker-wallet test; the repeated-param error preserves b=1).
Both addressed:
Thu, Jul 30
Five of the six addressed; pushing back on one:
Fixed: an empty ?action= is now treated as absent — falling back like any non-agora link — in both the Cashtab parser and pay.e.cash, consistent with the spec's empty-value rule and with how empty price/quantity are already handled. (The token screen already treated an empty action as no action.) Added a parser test.
Addressed all four findings, then did a full audit of the deep-link path and found (and fixed) three more things review hadn't caught:
All three addressed:
All three addressed:
Fixed the offer-refresh Major: fetchAndPrepareActiveOffers was unconditionally re-selecting the best (cheapest affordable) offer on every fetch, including the refetch a websocket trade or balance change triggers. Since a BUY deep link's offer override only runs once, a refresh would reset the selection to cheapest and erase the prefilled quantity for a pricier offer that was chosen to fill it. The auto-select now skips once a deep link has applied its selection (guarded on prepopulateBuyQtyApplied); non-deep-link buys are unchanged, and cross-token navigation still auto-selects because the tokenId reset clears that flag.
Both fixed:
Two fixes and one I'd push back on:
Worked through all six CodeRabbit findings:
Both minors addressed:
LIST / quantity docs: added the explicit rule to the LIST section of agora-deeplink.md — a quantity on a LIST is invalid and the wallet must surface a validation error (symmetric with BUY's price rule) — and removed a stale "(and quantity)" reference in the LIST validation steps. The parsers already enforced this; the doc now matches.
BUY on an NFT collection: the token screen now refuses a BUY on an NFT parent (collection) with a toast, mirroring LIST — you don't buy a collection token itself, you buy its child NFTs on their own screens. The refusal keys on isNftParent only, deliberately not the "listable" set: XECX and Firma are redeem-only (not listable) but they do have an Agora orderbook you can buy from, so gating BUY on getListActionForToken() would have wrongly blocked them (guarded by the existing "BUY is allowed for XECX" test). Added a test for the collection-BUY refusal.
Regression green (224 tests), prettier + arc lint clean.
More CodeRabbit findings
Addressed the remaining CodeRabbit minors:
Addressed the remaining CodeRabbit minors
Wed, Jul 29
Fixed CodeRabbit's two majors:
Fix BUY+price parser error + prefill wipe-on-refresh
The Diff Testing build (cashtab-tests + ai-review) is failing before it runs — the log says "Snapshot dependency failed to start: Automated Deployments / Bitcoin ABC Infra / Bitcoin-ABC Infra Checkout". Looks like a CI infra issue on your end rather than the diff (base is on current master, arc lint passes, and the cashtab suite passes locally). Anything I can do, or is this one for an admin? @bytesofman @Fabien
Re-trigger CI
Address CodeRabbit follow-ups
Implement smarter BUY (quantity) + address CodeRabbit findings
Mon, Jul 27
Sat, Jul 25
Re-submitting with arc lint actually run: installed the full local lint toolchain (clang-format 16, shellcheck, ruff, yamllint, mypy, djlint, phpcs) so .arclint loads, and arc lint over this diff passes clean (verified it flags planted violations). No code change from the prior diff.
Address review feedback (bytesofman + CodeRabbit):
Abandoning this in favor of the approach you pointed at. You're right: returning a wallet signature to a website via a URL callback is a web-integration / auth-shaped feature, not eCash-specific, and the redirect + exfiltration surface doesn't belong bolted onto Sign & Verify. I'll put up a cashtab-connect signMessage request instead, mirroring the existing requestAddress approval flow (in-page popup, origin-bound, signature returned in memory). Thanks for the steer.
Fri, Jul 24
Currently cashtab-connect only works on the browser extension, but not on the web version of Cashtab (mobile and desktop). The problem I have is that users have to manually paste a signature from cashtab back to the dapp and it leads to a clunky user experience. The ideal solution is user clicks "sign in cashtab" button, it opens cashtab (web or extension) with the message prefilled and asks if you want to sign, when you approve, the signature is sent to the dapp.
The reason for this feature is because cashtab-connect is only available with the extension, which is not available to users on mobile or desktop users without the extension installed. Cashtab-connect could theoretically allow you to sign a message in cashtab and have it return it directly to proofofwriting's page code. The signature acts like a private key to a "pocket" wallet that is created in proofofwriting. A small pocket where you can keep pocket change to be spent on the site without having to toggle back and forth between proofofwriting and cashtab. If cashtab-connect existed for the non-extension version of Cashtab, I'd leverage that, but it seems that is not possible. This was an attempt at a workaround for the web wallet. I'm trying to make the creation of the Pocket wallet less clunky. Right now you have to copy and paste a message into cashtab, sign, then manually toggle back to proofofwriting and paste the signature into a box. This was going to make it so you just click sign, then approve and the signature gets sent back to proofofwriting.
Fixed 1.
Refuse LIST for XECX/Firma (redeem-only), add tests
Wed, Jul 22
Rebased onto latest master
Move agora links to /token, add pay.e.cash and docs.e.cash support
Tue, Jul 21
All three done.
Move agora links to /token, add pay.e.cash and docs.e.cash support).
Done — implemented it in this diff.
Implemented the spec in this diff, added tests and pay.e.cash support
Sun, Jul 19
Yeah, this makes sense to me. A sellNft-specific link is too narrow, and since Agora isn't a Cashtab thing, a general standard is the right call. Lines up with T3760.
Reworked as a spec doc per review; implementation to follow.
Jul 18 2026
Jul 17 2026
Jul 15 2026
Confirmed the OP_10/OP_11 encoding, payload order, and validation match the proofofwriting.com emitter exactly. LGTM.