Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Switch to 3cities #2

Open
wants to merge 40 commits into
base: master
Choose a base branch
from
Open

[WIP] Switch to 3cities #2

wants to merge 40 commits into from

Conversation

ryanberckmans
Copy link
Member

Switch payment engine to 3cities

Send and verify payments using the 3cities decentralized payment processor instead of by this plugin itself.

Goals of this switch include

  • prevent pretix-eth from needing to own any code that touches onchain. All onchain interactions are now owned by 3cities in the 3cities codebase.
  • enable users to pay using a variety of tokens and L2s, with the specific token and chain used determined at the moment the user submits their payment transaction.

WIP missing components

  • the 3cities payment verifier is currently a stub
  • the 3cities client and verifier are expected to be running on localhost and can't yet be fully configured in the plugin settings
  • payments must currently be in USD. Both pretix-eth and 3cities support ETH payments, but the glue work for pretix to pass 3cities an offered ETHUSD exchange rate is not yet complete

Note that before adopting 3cities, a user's smart contract wallet eip1271 signature was verified in this pretix-eth server before the user was allowed to send their payment transaction. eip1271 signatures are now verified in the 3cities clientside iframe and serverside verifier instead of in pretix-eth.

The new pretix_eth.verifier.verify_payment synchronously calls the
3cities payment verifier grpc service, which currently must be running
on localhost.

This stub calls the live grpc service but with a fake API.

Also adds new package threecities.* which is the 3cities grpc service
generated code for the python service client.

Running the 3cities grpc server requires a valid SSL certificate on the
serverside. grpc requires SSL even to run on localhost. See instructions
on setting up self-signed certificate.
This commit begins the processs of payments being submitted and verified
using the 3cities decentralized payment processor instead of by this
plugin itself.

Goals of this switch include
- prevent pretix-eth from needing to own any code that touches onchain.
  All onchain interactions are now owned by 3cities in the 3cities
  codebase.
- enable users to pay using a variety of tokens and L2s, with the
  specific token and chain used determined at the moment the user
  submits their payment transaction.

Missing components as of this initial commit
- the 3cities payment verifier is currently a stub
- the 3cities client and verifier are expected to be running on
  localhost and can't yet be fully configured in the plugin settings
- payments must currently be in USD. Both pretix-eth and 3cities support
  ETH payments, but the glue work for pretix to pass 3cities an offered
  ETHUSD exchange rate is not yet complete

Note that before adopting 3cities, a user's smart contract wallet
eip1271 signature was verified in this pretix-eth server before the user
was allowed to send their payment transaction. eip1271 signatures are
now verified in the 3cities clientside iframe and serverside verifier
instead of in pretix-eth.
@ryanberckmans ryanberckmans requested a review from kvbik May 6, 2024 16:48
Support automatically closing the 3cities iframe when the CloseIframe
message is received from the 3cities client.
This ensures that the 3cities pop-up is correctly rendered in desktop
view when using pretix on desktop.

return grpc_ca_root_cert_file_path

grpc_ca_root_cert_file_path = get_grpc_ca_root_cert_file_path()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to make sure, that in production, no file is being created in this runtime. We can deploy anything before hand of course.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great! Currently, the plugin expects to find the file in the configured path, but doesn't create the file during python execution.

@kvbik
Copy link
Collaborator

kvbik commented May 23, 2024

let's try this :)

ryanberckmans and others added 16 commits June 16, 2024 16:37
ETH payments are now supported using 3cities.

When a customer places an order, the current live USD/ETH rate is
snapshotted into their order. The customer may then complete an ETH
payment using their locked-in USD/ETH rate as long as their pending
payment hasn't expired.

As always, the specific token and chain the customer ends up paying is
determined just-in-time when the customer connects their wallet in
3cities to pay. The customer might end up paying ETH or a stablecoin,
it's not known until payment time.

ETH payments in 3cities are now routed through a proxy contract that
does nothing except completes the ETH transfer and emits an
ERC20-compliant Transfer event to help with offchain payment detection.
do not downgrade pretix becuase of this
The upgrade from 2024.2 to 2024.6.0 caused a regression in how
template.render handled being passed additional context while also being
passed the django Request. The bug impact was that payment details
couldn't be submitted from the frontend because the POST failed due to
missing csrf token because csrf_token was undefined in web3modal.html
due to django Request no longer being correctly bundled into the context
passed to the template. This change fixes this.
This downgrades minimum pretix from 2024.6 to 2024.2 as we were having a
"csrf_token undefined" issue which there is some evidence may be
resolved by downgrading.
afaik, signature can be much longer than the old max length eg. with
ERC-6492 smart wallets.

Typo in views.py caused recipient_address to be malformed.
Add new insecure and untrusted admin convenience fields to model,
control, and exporter.

Submit tx details on 3cities TransactionSigned iframe msg instead of on
Checkout iframe msg. This causes the details to be saved before
transaction confirmation, which reduces the time window and thus risk of
the race condition where the user closes the tab before tx details are
saved in pretix.

Pass plugin payment receiver address to 3cities, such that the actual
address to which funds are sent is now controlled via plugin config.
ryanberckmans and others added 13 commits July 9, 2024 12:42
There are some polygon zkEVM payment bugs to fix before reenabling.
queuePromise is a library from 3cities that helps avoid race conditions
when writing to async storage with localForage.

queuePromise should be published as an ordinary npm module, but it's not
yet, so instead I have included a compiled version of it here.
Background:

When the user signs a payment transaction, 3cities will provide those
transaction details to the pretix clientside webpage via iframe message
passing.

Those transaction details must then be successfully submitted to the
pretix server.

If submission fails for any reason, the payment details will be lost,
and then the payment can't automatically confirm, and worse, there will
be no record at all that the user ever paid. So the user will have paid
money for nothing, and must reconcile by contacting support.

Before this revamp, transaction details received via iframe message
passing would be submitted to the pretix server. Any submission errors
would result in retrying in perpetuity with exponential backoff.

However, the retry system before this revamp was only in-memory and
transaction details would be permanently lost if the user refreshed the
page prior to success.

With this revamp, transaction details received by 3cities iframe msg
will be immediately saved into local storage before any server
submission is attempted. Then, a monitoring system will detect pending
transaction details and attempt server submission.

This new monitoring system is resilient to page refreshes, network
outages, and multiple concurrent pending orders made by the customer on
the same device.

All the user must do is keep their order page open (or open it again if
closed) and then any saved pending transaction details will be submitted
automatically and marked as submitted.

If the transaction details are received by 3cities iframe msg but saving
them into local storage fails, then payment details have been
permanently lost (the user paid money for nothing), and a "critical
error" is displayed to the user and asks them to contact support.

Note that we use the great 'localForage' library which abstracts over
local storage adapters to make this solution cross-platform, so the
actual storage used might be localStorage, IndexedDB, etc.

Also, this fixes a bug where if the user loaded their order page after
they had successfully paid but before the payment was confirmed, then
payment confirmation would never be automatically detected without
refreshing the page.
This allows selection between the 3cities interface on 3cities.xyz
(production interface with mainnet chains), prod-test.3cities.xyz (prod
staging interface with mainnet chains), and test.3cities.xyz (staging
interface with testnet chains).
Payments are now actually verified when runnin the confirm_payments job.
To help avoid data loss when iframe might be closed during transaction
signing.
useful when running for an expected big selling wave
…ation

Don't attempt to re-verify Ethereum payments where verification was
known to have permanently failed.
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.

2 participants