Skip to content

Alpha - #47

Merged
0xBeycan merged 8 commits into
masterfrom
alpha
Jul 15, 2026
Merged

Alpha#47
0xBeycan merged 8 commits into
masterfrom
alpha

Conversation

@0xBeycan

Copy link
Copy Markdown
Member

No description provided.

0xBeycan and others added 8 commits July 15, 2026 14:53
Buy with CryptoPay button on the product page, ported from premium.

- views/instant.php, src/js/instant.js (included into main.js via gulp-include)
- Payment.php: after_add_to_cart_form action, instant(), init() and
  beforePaymentStarted() branches
- acceptInstantPayments is now a real switcher instead of a premium placeholder

Uses Gateway::ID for the order payment method, since Lite's gateway id is
cryptopay_lite, not premium's cryptopay.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Section 5 outcome: 2 done, 2 cancelled.

- Instant and Arbitrum/Optimism: done.
- OFAC/Sanctions cancelled: the only provider (Coinfirm) was absorbed into
  Lukka, its api key page is a dead redirect and it was enterprise-only, so a
  free Lite user could never enable it. Chainalysis' free oracle noted as the
  option if we revisit.
- Refund cancelled: architecture. Premium drives networks from PHP, Lite has
  them predefined in JS, so refund cannot restrict the widget to the original
  network and token.

Also corrected 5.4, which described a PHP-only change: Lite's network metadata
actually lives in cryptopay-ts (lite branch), so PHP alone would have made the
new networks invisible at checkout.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
TableCreator::$charset is a typed property with no default, assigned only
inside the has_cap('collation') branch but read unconditionally when building
the CREATE TABLE. On any database that answers no, PHP 8 fatals with "must not
be accessed before initialization".

MySQL says yes, which is why this never surfaced in production. SQLite says no,
so it takes down every install running the SQLite integration, including the
plugin's own wp.org Live Preview: blueprint.json lands the visitor on the
settings page, and the moment they save a wallet address the model is
constructed and the site white-screens.

Found while driving the setup wizard in WordPress Playground.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Both adapters reach Reown's relay and cannot connect without a project id:
AppKit builds its modal with it, legacy WalletConnect opens a relay session with
it. Their connect() throws when it is empty, so the option is dead the moment a
customer picks it. Both shipped switched on by default with no id set, and
isDetected() returns true unconditionally, so a fresh install has always offered
customers wallets that cannot work.

Three layers, because none of them is sufficient alone:

- getWallets() drops them at runtime when there is no id. This is what repairs
  the installs already out there; changing the defaults does nothing for a site
  whose option already says true.
- The csf_*_save filter refuses to switch them on without an id and explains
  why. A field's own validate() only receives that field's value, so it cannot
  see wcProjectId; the save filter is the only place the two can be compared.
- The switchers are hidden until an id exists. The fourth element marks the rule
  global: without it CSF resolves the controller within the field's own
  container, wcProjectId lives in another section, and the rule would never
  match, hiding the switch forever even for someone who has an id. Verified both
  ways in a browser.

The dependency does not make the filter redundant. CSF serialises the whole
form, so a hidden switch still posts its old value: turn AppKit on, clear the
id, save, and without the filter the broken combination is written back.

Adding an id now switches AppKit on by itself, since anyone who goes and fetches
one wants what it unlocks. Only on the transition, so a deliberate switch-off is
never undone. Legacy WalletConnect is left alone: on alongside AppKit is the
conflict its own description warns about.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The top deactivation reason on wp.org is "it doesn't work / I can't see it at
checkout". Two settings decide that, and the order between them is forced rather
than chosen: with no wallet address the Loader never constructs
WooCommerce\Initialize, so the gateway is never registered and the "Click to
activate" link in the settings pointed at a WooCommerce section that did not yet
exist. Then the gateway itself ships disabled, as every WooCommerce gateway
does. Neither told anyone.

SetupStatus is the single source of truth for "will this appear at checkout?".
The wizard walks it in the only order that works; the admin badge reports the
same answer permanently, which matters more than the wizard: the wizard runs
once, the badge is still there when someone turns their last network off six
months later.

Notes for the next person:

- EvmChains::ensureDefaults() exists because CSF only persists its defaults when
  the whole option is still empty. The wizard writes before the settings page
  has ever been opened, so without seeding, the network and wallet lists would
  be absent and read back as "nothing is active" - the wizard would have caused
  the exact bug it is meant to fix.
- The gateway id moved to Constants. Reading it off the gateway class autoloads
  something that extends WC_Payment_Gateway, which fatals when WooCommerce is
  inactive, i.e. exactly when the WooCommerce check needs to run.
- The wizard is one view file with an explicit kses whitelist. The view helper
  derives allowed attributes from the first occurrence of each tag, so splitting
  it up, or trusting the default, silently drops `checked` from every checkbox
  and `name`/`value` from the skip button, which then behaves as Continue.
- A rejected value is carried in a transient rather than the query string, to
  keep the wallet address out of history and access logs.

Verified end to end in WordPress Playground: activation redirects, validation
holds, the wizard's choices land in the database, and WooCommerce's own Payments
screen reports CryptoPay Lite as Active.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Working notes, not something that belongs in a published plugin. Recoverable
from history at 44e030f if it is wanted again.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The plugin's strongest differentiator was buried under the video and stated as a
feature ("No commission") rather than as the problem it solves. The universal
complaint in this category is the fee surprise: custodial services take the
payment into their own wallet, deduct their cut, and forward the rest, so the
merchant finds out after the sale that what arrived is not what was sent.

Says why we cannot charge a commission rather than that we choose not to: being
peer to peer means the money never passes through us. Deliberately names no
competitor and quotes no figures. wp.org's guidelines take a dim view of
disparaging other plugins, and the anecdote this came from is one user's review
of someone else's product that we have not verified and would be republishing as
fact. The argument is stronger on its own merits anyway.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@0xBeycan
0xBeycan merged commit 9184418 into master Jul 15, 2026
1 check passed
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