unlock-protocol / unlock

Ʉnlock is a protocol for memberships built on a blockchain.
https://unlock-protocol.com
MIT License
844 stars 251 forks source link

fix(unlock-app): checkout frame errors #14912

Open iMac7 opened 3 weeks ago

iMac7 commented 3 weeks ago

Description

Issues

Fixes #14888 Refs #

Checklist:

Indeed an erc20 approval is needed first. This handles that by having the first button click as the approval and the second as the actual purchase, lmk if that's confusing or a more elegant way, I don't see a way to 'batch' those 2 together in a single transaction so far :thinking: .

As for checking if a user has a membership before the purchase, this can happen by cancelling a transaction midway, because the user's wallet details are not accessible elsewhere. Doing that would throw an error anyway so I'm assuming a failed purchase (because you already have a key) does the same and it's sort of an 'acceptable' error

https://github.com/user-attachments/assets/72ada736-41af-4691-be4a-172774addc6b

Release Note Draft Snippet

image

julien51 commented 3 weeks ago

Indeed an erc20 approval is needed first. This handles that by having the first button click as the approval and the second as the actual purchase, lmk if that's confusing or a more elegant way, I don't see a way to 'batch' those 2 together in a single transaction so far 🤔 .

In the case of an ERC20 lock, you first need to check if there is an existing approval and if that approval is "enough" ( > price). I don't think you can "batch" the 2 tx. The user would first need to approve and 2nd need to send the purchase.

julien51 commented 3 weeks ago

As for checking if a user has a membership before the purchase, this can happen by cancelling a transaction midway, because the user's wallet details are not accessible elsewhere. Doing that would throw an error anyway so I'm assuming a failed purchase (because you already have a key) does the same and it's sort of an 'acceptable' error

No, you need to actually perform a check and can't rely on the fact that there is an error, because the purchase could fail for other reasons (sold out.. etc). So this means we can't show a Mint button right away but start with an intermediary action like Continue. This button would then trigger an action where you can verify if the user does indeed own a specific key to the lock. If they do, you can show a message saying "you already have a key"... and if they don't you can check if an approval is needed. If it is, trigger the approval, and if they don't (or once they have done it), just trigger the actual purchase tx.

What do you think?

iMac7 commented 3 weeks ago

to get the user address, they are first required to sign a dummy message to prompt the wallet connect. The user's address is only available in a transaction context so this hacky way is the only one I see to get that without an error or an actual transaction. It shows below that I'm a member even though I can still buy another key, just for testing but it's implemented in the code.

https://www.loom.com/share/722c2376444a4b6393963e43a8398669?sid=a407e3b8-a2d5-483a-a2a9-e5971bc7754d

julien51 commented 3 weeks ago

to get the user address, they are first required to sign a dummy message to prompt the wallet connect.

You can get it from the frame as long as the user has interracted with it, which is why the "Continue" button is useful :)

iMac7 commented 2 weeks ago

to get the user address, they are first required to sign a dummy message to prompt the wallet connect.

You can get it from the frame as long as the user has interracted with it, which is why the "Continue" button is useful :)

This might be specific to the current version of framesjs or only on the local debugger not sure, but only a button with action 'mint' or 'tx' is able to give a prompt to connect a wallet. the continue button would have a 'post' or 'post_redirect' property which doesn't connect a wallet but only navigates to another page (I just confirmed locally that it doesn't).

Maybe in prod it might behave differently but in the docs I don't see any other way to get the address with no tx. Connecting a wallet is better handled with the useFrame() hook which is used inside react, but it's not handled as gracefully when dealing with the server side of framesjs like in this case.

https://framesjs.org/guides/transactions#using-the-connected-wallet-address This doesn't help much for an unauthenticated user, maybe I don't get it :thinking:

Which kind of action button ( https://framesjs.org/reference/core/Button#button ) do you suggest for 'continue'? I seem to hit a wall on that one :face_exhaling:

julien51 commented 2 weeks ago

This might be specific to the current version of framesjs or only on the local debugger not sure, but only a button with action 'mint' or 'tx' is able to give a prompt to connect a wallet. the continue button would have a 'post' or 'post_redirect' property which doesn't connect a wallet but only navigates to another page (I just confirmed locally that it doesn't).

You have the fid, and then you can get the wallet address as soon as the user has interracted wuth the frame https://framesjs.org/reference/js/getAddressesForFid#usage