-
-
Notifications
You must be signed in to change notification settings - Fork 252
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
fix(unlock-app): checkout frame errors #14912
base: master
Are you sure you want to change the base?
Changes from 5 commits
07a4f8a
450460c
2bcea68
448f6d6
ef8a4dc
03cbc88
cc72ef8
1acfab2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { Abi, encodeFunctionData, erc20Abi } from 'viem' | ||
import { frames } from '../frames' | ||
import { transaction } from 'frames.js/core' | ||
|
||
export const POST = frames(async (ctx) => { | ||
if (!ctx?.message) { | ||
throw new Error('Invalid frame message') | ||
} | ||
|
||
const lock = ctx.state.lock! | ||
const { address: lockAddress, network, priceForUser } = lock | ||
|
||
const calldata = encodeFunctionData({ | ||
abi: erc20Abi, | ||
functionName: 'approve', | ||
args: [lockAddress as `0x${string}`, BigInt(priceForUser!)], | ||
}) | ||
|
||
return transaction({ | ||
chainId: `eip155:${network}`, | ||
method: 'eth_sendTransaction', | ||
params: { | ||
abi: erc20Abi as Abi, | ||
to: ctx.state.lock?.tokenAddress as `0x${string}`, | ||
data: calldata, | ||
value: '0x0', | ||
}, | ||
}) | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import { transaction } from 'frames.js/core' | ||
import { | ||
checkAllowance, | ||
getKeyPrice, | ||
isMember as checkIsMember, | ||
} from '../components/utils' | ||
import { frames } from '../frames' | ||
|
||
export const POST = frames(async (ctx) => { | ||
if (!ctx?.message) { | ||
throw new Error('Invalid frame message') | ||
} | ||
|
||
const userAddress = ctx.message.address as `0x${string}` | ||
const lock = ctx.state.lock! | ||
const { address: lockAddress, network, tokenAddress } = lock | ||
|
||
const isMember = await checkIsMember(lockAddress, network, userAddress) | ||
lock.isMember = isMember | ||
|
||
const keyPrice = await getKeyPrice({ | ||
lockAddress, | ||
network, | ||
userAddress, | ||
}) | ||
lock.priceForUser = keyPrice | ||
|
||
if (tokenAddress) { | ||
const allowance = await checkAllowance( | ||
lockAddress, | ||
Number(network), | ||
userAddress as string, | ||
tokenAddress! | ||
) | ||
if (Number(allowance) >= Number(keyPrice)) { | ||
lock.erc20Approved = true | ||
} | ||
} | ||
|
||
return transaction({ | ||
chainId: `eip155:${network}`, | ||
method: 'eth_signTypedData_v4', | ||
params: { | ||
domain: {}, | ||
types: { | ||
Message: [{ name: 'Signature request', type: 'string' }], | ||
}, | ||
primaryType: 'Message', | ||
message: { | ||
'Signature request': 'Please sign this message to connect your wallet.', | ||
}, | ||
}, | ||
}) | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,8 +2,6 @@ import { Abi, encodeFunctionData } from 'viem' | |
import { frames } from '../frames' | ||
import { transaction } from 'frames.js/core' | ||
import { PublicLockV14 } from '@unlock-protocol/contracts' | ||
import { Web3Service } from '@unlock-protocol/unlock-js' | ||
import networks from '@unlock-protocol/networks' | ||
|
||
const abi = PublicLockV14.abi | ||
|
||
|
@@ -12,30 +10,14 @@ export const POST = frames(async (ctx) => { | |
throw new Error('Invalid frame message') | ||
} | ||
|
||
const userAddress = ctx.message.connectedAddress! | ||
const userAddress = ctx.message.address! | ||
const { address: lockAddress, priceForUser } = ctx.state.lock! | ||
const network = Number(ctx.state.lock!.network) | ||
const lockAddress = ctx.state.lock!.address | ||
|
||
async function getKeyPrice() { | ||
const web3Service = new Web3Service(networks) | ||
const mydata = '0x' | ||
let price = await web3Service.purchasePriceFor({ | ||
lockAddress, | ||
userAddress: userAddress, | ||
network, | ||
data: mydata, | ||
referrer: userAddress, | ||
}) | ||
price = price.toString() | ||
return price | ||
} | ||
|
||
const keyPrice = await getKeyPrice() | ||
|
||
const calldata = encodeFunctionData({ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please use unlock'js walletService here as well so this supports any version of the lock contract! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I ran into errors getting the abi with |
||
abi, | ||
functionName: 'purchase', | ||
args: [[keyPrice], [userAddress], [userAddress], [userAddress], ['0x']], | ||
args: [[priceForUser], [userAddress], [userAddress], [userAddress], ['0x']], | ||
}) | ||
|
||
return transaction({ | ||
|
@@ -45,7 +27,7 @@ export const POST = frames(async (ctx) => { | |
abi: abi as Abi, | ||
to: lockAddress as `0x${string}`, | ||
data: calldata, | ||
value: keyPrice.toString(), | ||
value: priceForUser, | ||
}, | ||
}) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need to use that! unlock-js has the logic you need to use.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn’t catch that, the encodeFunctionData part or the entire erc20 approve 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I think you should first check if the user has already approved enough (and you can compute the amount that needs to be approved based on the ehckout config (especially if it supports renewals)
Sorry my initial comment was unclear. Check unlock-js where there is already logic around how to compute the amount to be approved.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seen the logic in unlock-js/src/PublicLock/v10/getPurchaseKeysArguments to account for renewals and done it slightly differently.
my approach now checks if a lock is renewable to decide whether to render the approve button, so you can always approve a different amount before the purchase to replace any previous approval