Skip to content

Commit

Permalink
Implement actions using userOpBuilder service instead of permissionle…
Browse files Browse the repository at this point in the history
…ss.js (#2758)
  • Loading branch information
KannuSingh authored Sep 3, 2024
1 parent dea32cf commit 13cb0ff
Show file tree
Hide file tree
Showing 30 changed files with 13,237 additions and 17,536 deletions.
2 changes: 1 addition & 1 deletion apps/laboratory/next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const cspHeader = `
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
img-src * 'self' data: blob: https://walletconnect.org https://walletconnect.com https://secure.walletconnect.com https://secure.walletconnect.org https://tokens-data.1inch.io https://tokens.1inch.io https://ipfs.io https://lab.web3modal.com;
font-src 'self' https://fonts.gstatic.com;
connect-src 'self' https://rpc.walletconnect.com https://rpc.walletconnect.org https://relay.walletconnect.com https://relay.walletconnect.org wss://relay.walletconnect.com wss://relay.walletconnect.org https://pulse.walletconnect.com https://pulse.walletconnect.org https://api.web3modal.com https://api.web3modal.org wss://www.walletlink.org https://o1095249.ingest.sentry.io;
connect-src 'self' https://react-wallet.walletconnect.com https://rpc.walletconnect.com https://rpc.walletconnect.org https://relay.walletconnect.com https://relay.walletconnect.org wss://relay.walletconnect.com wss://relay.walletconnect.org https://pulse.walletconnect.com https://pulse.walletconnect.org https://api.web3modal.com https://api.web3modal.org wss://www.walletlink.org https://o1095249.ingest.sentry.io;
frame-src 'self' https://verify.walletconnect.com https://verify.walletconnect.org https://secure.walletconnect.com https://secure.walletconnect.org;
object-src 'none';
base-uri 'self';
Expand Down
1 change: 0 additions & 1 deletion apps/laboratory/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@
"framer-motion": "10.17.9",
"next": "14.2.3",
"next-auth": "4.24.5",
"permissionless": "0.1.31",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-icons": "4.12.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { useEffect } from 'react'
import { Button, Stack } from '@chakra-ui/react'
import { privateKeyToAccount } from 'viem/accounts'
import { useChakraToast } from '../Toast'
import { LOCAL_SIGNER_KEY, getItem } from '../../utils/LocalStorage'
import { LOCAL_SIGNER_KEY, getLocalStorageItem } from '../../utils/LocalStorage'
import { createCredential } from 'webauthn-p256'
import { useWagmiPermissionsSync } from '../../context/WagmiPermissionsSyncContext'
import { usePasskey } from '../../context/PasskeyContext'

export function WagmiCreatePasskeySignerTest() {
const { isPasskeyAvailable, setPasskey, passkeyId } = useWagmiPermissionsSync()
const { isPasskeyAvailable, setPasskey, passkeyId } = usePasskey()
const toast = useChakraToast()

async function handleCreatePasskey() {
Expand All @@ -31,7 +31,7 @@ export function WagmiCreatePasskeySignerTest() {
}

useEffect(() => {
const storedLocalSignerPrivateKey = getItem(LOCAL_SIGNER_KEY)
const storedLocalSignerPrivateKey = getLocalStorageItem(LOCAL_SIGNER_KEY)
if (storedLocalSignerPrivateKey) {
privateKeyToAccount(storedLocalSignerPrivateKey as `0x${string}`)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,14 @@ import { useChakraToast } from '../Toast'
import { encodeFunctionData, parseEther } from 'viem'
import { abi as donutContractAbi, address as donutContractaddress } from '../../utils/DonutContract'
import { sepolia } from 'viem/chains'
import { useWagmiPermissionsAsync } from '../../context/WagmiPermissionsAsyncContext'
import { useERC7715PermissionsAsync } from '../../hooks/useERC7715PermissionsAsync'
import { useLocalEcdsaKey } from '../../context/LocalEcdsaKeyContext'
import { useERC7715Permissions } from '../../hooks/useERC7715Permissions'
import { executeActionsWithECDSAAndCosignerPermissions } from '../../utils/ERC7715Utils'

export function WagmiPurchaseDonutAsyncPermissionsTest() {
const { grantedPermissions, wcCosignerData, privateKey, projectId } = useWagmiPermissionsAsync()
const { privateKey } = useLocalEcdsaKey()

const { executeActionsWithECDSAAndCosignerPermissions } = useERC7715PermissionsAsync({
chain: sepolia,
permissions: grantedPermissions,
projectId
})
const { grantedPermissions, pci } = useERC7715Permissions()

const {
data: donutsOwned,
Expand All @@ -35,40 +32,43 @@ export function WagmiPurchaseDonutAsyncPermissionsTest() {
async function onPurchaseDonutWithPermissions() {
setTransactionPending(true)
try {
if (!wcCosignerData) {
throw Error('No wc-cosigner data available')
}

if (!privateKey) {
throw new Error(`Unable to get dApp private key`)
}
if (!grantedPermissions) {
throw Error('No permissions available')
}
if (!pci) {
throw Error('No WC cosigner data(PCI) available')
}
const purchaseDonutCallData = encodeFunctionData({
abi: donutContractAbi,
functionName: 'purchase',
args: [1]
})
const purchaseDonutCallDataExecution = [
{
target: donutContractaddress as `0x${string}`,
to: donutContractaddress as `0x${string}`,
value: parseEther('0.0001'),
callData: purchaseDonutCallData
data: purchaseDonutCallData
}
]
const txHash = await executeActionsWithECDSAAndCosignerPermissions({
actions: purchaseDonutCallDataExecution,
chain: sepolia,
ecdsaPrivateKey: privateKey as `0x${string}`
ecdsaPrivateKey: privateKey as `0x${string}`,
permissions: grantedPermissions,
pci
})
if (txHash) {
toast({
title: 'Transaction success',
description: txHash,
title: 'UserOp submitted successfully',
description: `UserOp Hash: ${txHash}`,
type: 'success'
})
await fetchDonutsOwned()
}
} catch (error) {
// Console.log(error)
toast({
title: 'Transaction Failed',
description: `${error}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,14 @@ import { useState } from 'react'
import { useChakraToast } from '../Toast'
import { encodeFunctionData, parseEther } from 'viem'
import { abi as donutContractAbi, address as donutContractaddress } from '../../utils/DonutContract'
import { useERC7715PermissionsSync } from '../../hooks/useERC7715PermissionsSync'
import { useWagmiPermissionsSync } from '../../context/WagmiPermissionsSyncContext'
import { useERC7715Permissions } from '../../hooks/useERC7715Permissions'
import { usePasskey } from '../../context/PasskeyContext'
import { sepolia } from 'viem/chains'
import { executeActionsWithPasskeyAndCosignerPermissions } from '../../utils/ERC7715Utils'

export function WagmiPurchaseDonutSyncPermissionsTest() {
const { grantedPermissions, wcCosignerData, passkeyId, projectId } = useWagmiPermissionsSync()
const { executeActionsWithPasskeyAndCosignerPermissions } = useERC7715PermissionsSync({
chain: sepolia,
permissions: grantedPermissions,
projectId
})
const { passkeyId } = usePasskey()
const { grantedPermissions, pci } = useERC7715Permissions()

const {
data: donutsOwned,
Expand All @@ -37,8 +34,8 @@ export function WagmiPurchaseDonutSyncPermissionsTest() {
if (!grantedPermissions) {
throw Error('No permissions available')
}
if (!wcCosignerData) {
throw Error('No wc-cosigner data available')
if (!pci) {
throw Error('No WC cosigner data(PCI) available')
}

const purchaseDonutCallData = encodeFunctionData({
Expand All @@ -48,20 +45,22 @@ export function WagmiPurchaseDonutSyncPermissionsTest() {
})
const purchaseDonutCallDataExecution = [
{
target: donutContractaddress as `0x${string}`,
to: donutContractaddress as `0x${string}`,
value: parseEther('0.0001'),
callData: purchaseDonutCallData
data: purchaseDonutCallData
}
]
const txHash = await executeActionsWithPasskeyAndCosignerPermissions({
actions: purchaseDonutCallDataExecution,
chain: sepolia,
passkeyId,
wcCosignerData
permissions: grantedPermissions,
pci
})
if (txHash) {
toast({
title: 'Transaction success',
description: txHash,
title: 'UserOp submitted successfully',
description: `UserOp Hash: ${txHash}`,
type: 'success'
})
await fetchDonutsOwned()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,134 +3,102 @@ import { useAccount } from 'wagmi'
import { walletActionsErc7715 } from 'viem/experimental'
import { useCallback, useState } from 'react'
import { useChakraToast } from '../Toast'
import { createPublicClient, custom } from 'viem'
import { createWalletClient, custom, type Address, type Chain } from 'viem'
import { EIP_7715_RPC_METHODS } from '../../utils/EIP5792Utils'
import { useWalletConnectCosigner } from '../../hooks/useWalletConnectCosigner'
import { useWagmiAvailableCapabilities } from '../../hooks/useWagmiActiveCapabilities'
import { useWagmiPermissionsAsync } from '../../context/WagmiPermissionsAsyncContext'
import {
decodeUncompressedPublicKey,
encodePublicKeyToDID,
hexStringToBase64
} from '../../utils/EncodingUtils'
useWagmiAvailableCapabilities,
type Provider
} from '../../hooks/useWagmiActiveCapabilities'
import { useLocalEcdsaKey } from '../../context/LocalEcdsaKeyContext'
import { bigIntReplacer } from '../../utils/CommonUtils'
import { getSampleAsyncPermissions } from '../../utils/ERC7715Utils'
import { useERC7715Permissions } from '../../hooks/useERC7715Permissions'
import { getPurchaseDonutPermissions } from '../../utils/ERC7715Utils'
import { KeyTypes } from '../../utils/EncodingUtils'

export function WagmiRequestPermissionsAsyncTest() {
const { provider, supported } = useWagmiAvailableCapabilities({
method: EIP_7715_RPC_METHODS.WALLET_GRANT_PERMISSIONS
})
const { chain, address, isConnected } = useAccount()
const caip10Address = `eip155:${chain?.id}:${address}`

const {
projectId,
signer,
grantedPermissions,
clearGrantedPermissions,
setGrantedPermissions,
setWCCosignerData
} = useWagmiPermissionsAsync()
if (!isConnected || !provider || !address || !chain) {
return (
<Text fontSize="md" color="yellow">
Wallet not connected
</Text>
)
}
if (!supported) {
return (
<Text fontSize="md" color="yellow">
Wallet does not support wallet_grantPermissions rpc method
</Text>
)
}

return <ConnectedTestContent chain={chain} provider={provider} address={address} />
}

function ConnectedTestContent({
chain,
provider,
address
}: {
chain: Chain
provider: Provider
address: Address
}) {
const { grantedPermissions, clearGrantedPermissions, grantPermissions } = useERC7715Permissions()
const { signer } = useLocalEcdsaKey()
const [isRequestPermissionLoading, setRequestPermissionLoading] = useState<boolean>(false)
const { addPermission, updatePermissionsContext } = useWalletConnectCosigner(
caip10Address,
projectId
)
const toast = useChakraToast()

const onRequestPermissions = useCallback(async () => {
setRequestPermissionLoading(true)

if (!signer) {
throw new Error('PrivateKey signer not available')
}
if (!provider) {
throw new Error('No Provider available, Please connect your wallet.')
}
try {
const addPermissionResponse = await addPermission({
permissionType: 'donut-purchase',
data: '',
onChainValidated: false,
required: true
})
setWCCosignerData(addPermissionResponse)
const cosignerPublicKey = decodeUncompressedPublicKey(addPermissionResponse.key)

const dAppECDSAPublicKey = signer.publicKey
const dAppSecp256k1DID = encodePublicKeyToDID(dAppECDSAPublicKey, 'secp256k1')
const coSignerSecp256k1DID = encodePublicKeyToDID(cosignerPublicKey, 'secp256k1')
if (!signer) {
throw new Error('PrivateKey signer not available')
}
if (!provider) {
throw new Error('No Provider available, Please connect your wallet.')
}

const publicClient = createPublicClient({
const walletClient = createWalletClient({
account: address,
chain,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
transport: custom(provider)
}).extend(walletActionsErc7715())
const samplePermissions = getSampleAsyncPermissions([coSignerSecp256k1DID, dAppSecp256k1DID])
const approvedPermissions = await publicClient.grantPermissions(samplePermissions)
if (approvedPermissions) {
await updatePermissionsContext({
pci: addPermissionResponse.pci,
context: {
expiry: approvedPermissions.expiry,
signer: {
type: 'donut-purchase',
data: {
ids: [addPermissionResponse.key, hexStringToBase64(dAppECDSAPublicKey)]
}
},
signerData: {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-non-null-asserted-optional-chain
userOpBuilder: approvedPermissions.signerData?.userOpBuilder!
},
permissionsContext: approvedPermissions.permissionsContext,
factory: approvedPermissions.factory || '',
factoryData: approvedPermissions.factoryData || ''
}
})
setGrantedPermissions(approvedPermissions)
setRequestPermissionLoading(false)
toast({
type: 'success',
title: 'Permissions Granted',
description: JSON.stringify(approvedPermissions, bigIntReplacer)
})

return
}
toast({ title: 'Error', description: 'Failed to obtain permissions' })
const purchaseDonutPermissions = getPurchaseDonutPermissions()
const response = await grantPermissions(walletClient, {
permissions: purchaseDonutPermissions,
signerKey: {
key: signer.publicKey,
type: KeyTypes.secp256k1
}
})
toast({
type: 'success',
title: 'Permissions Granted',
description: JSON.stringify(response.approvedPermissions, bigIntReplacer)
})
} catch (error) {
toast({
type: 'error',
title: 'Permissions Erros',
description: error instanceof Error ? error.message : 'Some error occurred'
title: 'Request Permissions Errors',
description: error instanceof Error ? error.message : 'Unknown Error'
})
} finally {
setRequestPermissionLoading(false)
}
setRequestPermissionLoading(false)
}, [signer, provider])
if (!isConnected || !provider || !address) {
return (
<Text fontSize="md" color="yellow">
Wallet not connected
</Text>
)
}
if (!supported) {
return (
<Text fontSize="md" color="yellow">
Wallet does not support wallet_grantPermissions rpc method
</Text>
)
}
}, [signer, provider, address, chain, grantPermissions, toast])

return (
<Stack direction={['column', 'column', 'row']}>
<Button
data-test-id="request-permissions-button"
onClick={onRequestPermissions}
isDisabled={Boolean(
isRequestPermissionLoading || Boolean(grantedPermissions) || !isConnected
)}
isDisabled={Boolean(isRequestPermissionLoading || Boolean(grantedPermissions))}
isLoading={isRequestPermissionLoading}
>
Request Permissions
Expand Down
Loading

0 comments on commit 13cb0ff

Please sign in to comment.