-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
added ethers impl for ERC5792 and ERC7677 on laboratory (#2310)
- Loading branch information
1 parent
427914c
commit 220f752
Showing
6 changed files
with
430 additions
and
0 deletions.
There are no files selected for viewing
93 changes: 93 additions & 0 deletions
93
apps/laboratory/src/components/Ethers/EthersGetCallsStatusTest.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import { Button, Stack, Text, Input } from '@chakra-ui/react' | ||
import { useState } from 'react' | ||
import { useWeb3ModalAccount, useWeb3ModalProvider } from '@web3modal/ethers/react' | ||
import { EthereumProvider } from '@walletconnect/ethereum-provider' | ||
import { useChakraToast } from '../Toast' | ||
import { BrowserProvider } from 'ethers' | ||
import { type GetCallsStatusParams } from '../../types/EIP5792' | ||
import { EIP_5792_RPC_METHODS } from '../../utils/EIP5792Utils' | ||
|
||
export function EthersGetCallsStatusTest() { | ||
const [isLoading, setLoading] = useState(false) | ||
const [batchCallId, setBatchCallId] = useState('') | ||
|
||
const { address, chainId, isConnected } = useWeb3ModalAccount() | ||
const { walletProvider } = useWeb3ModalProvider() | ||
const toast = useChakraToast() | ||
|
||
async function onGetCallsStatus() { | ||
try { | ||
setLoading(true) | ||
if (!walletProvider || !address) { | ||
throw Error('user is disconnected') | ||
} | ||
if (!chainId) { | ||
throw Error('chain not selected') | ||
} | ||
if (!batchCallId) { | ||
throw Error('call id not valid') | ||
} | ||
const provider = new BrowserProvider(walletProvider, chainId) | ||
const batchCallsStatus = await provider.send(EIP_5792_RPC_METHODS.WALLET_GET_CALLS_STATUS, [ | ||
batchCallId as GetCallsStatusParams | ||
]) | ||
toast({ | ||
title: 'Success', | ||
description: JSON.stringify(batchCallsStatus), | ||
type: 'success' | ||
}) | ||
} catch { | ||
toast({ | ||
title: 'Error', | ||
description: 'Failed to get call status', | ||
type: 'error' | ||
}) | ||
} finally { | ||
setLoading(false) | ||
} | ||
} | ||
function isGetCallsStatusSupported(): boolean { | ||
if (walletProvider instanceof EthereumProvider) { | ||
return Boolean( | ||
walletProvider?.signer?.session?.namespaces?.['eip155']?.methods?.includes( | ||
EIP_5792_RPC_METHODS.WALLET_GET_CALLS_STATUS | ||
) | ||
) | ||
} | ||
|
||
return false | ||
} | ||
|
||
if (!isConnected || !address || !walletProvider) { | ||
return ( | ||
<Text fontSize="md" color="yellow"> | ||
Wallet not connected | ||
</Text> | ||
) | ||
} | ||
if (!isGetCallsStatusSupported()) { | ||
return ( | ||
<Text fontSize="md" color="yellow"> | ||
Wallet does not support wallet_getCallsStatus rpc method | ||
</Text> | ||
) | ||
} | ||
|
||
return ( | ||
<Stack direction={['column', 'column', 'row']}> | ||
<Input | ||
placeholder="0xf34ffa..." | ||
onChange={e => setBatchCallId(e.target.value)} | ||
value={batchCallId} | ||
isDisabled={isLoading} | ||
/> | ||
<Button | ||
data-test-id="get-calls-status-button" | ||
onClick={onGetCallsStatus} | ||
isDisabled={isLoading} | ||
> | ||
Get Calls Status | ||
</Button> | ||
</Stack> | ||
) | ||
} |
127 changes: 127 additions & 0 deletions
127
apps/laboratory/src/components/Ethers/EthersSendCallsTest.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
import { Button, Stack, Text, Spacer } from '@chakra-ui/react' | ||
import { useState } from 'react' | ||
import { useWeb3ModalAccount, useWeb3ModalProvider } from '@web3modal/ethers/react' | ||
import { EthereumProvider } from '@walletconnect/ethereum-provider' | ||
import { useChakraToast } from '../Toast' | ||
import { parseGwei, type Address } from 'viem' | ||
import { vitalikEthAddress } from '../../utils/DataUtil' | ||
import { BrowserProvider } from 'ethers' | ||
import { | ||
EIP_5792_RPC_METHODS, | ||
WALLET_CAPABILITIES, | ||
getCapabilitySupportedChainInfo | ||
} from '../../utils/EIP5792Utils' | ||
|
||
export function EthersSendCallsTest() { | ||
const [loading, setLoading] = useState(false) | ||
|
||
const { address, chainId, isConnected } = useWeb3ModalAccount() | ||
const { walletProvider } = useWeb3ModalProvider() | ||
const toast = useChakraToast() | ||
|
||
const atomicBatchSupportedChains = | ||
address && walletProvider instanceof EthereumProvider | ||
? getCapabilitySupportedChainInfo(WALLET_CAPABILITIES.ATOMIC_BATCH, walletProvider, address) | ||
: [] | ||
|
||
const atomicBatchSupportedChainNames = atomicBatchSupportedChains | ||
.map(ci => ci.chainName) | ||
.join(', ') | ||
const currentChainsInfo = atomicBatchSupportedChains.find( | ||
chainInfo => chainInfo.chainId === Number(chainId) | ||
) | ||
|
||
async function onSendCalls() { | ||
try { | ||
setLoading(true) | ||
if (!walletProvider || !address) { | ||
throw Error('user is disconnected') | ||
} | ||
if (!chainId) { | ||
throw Error('chain not selected') | ||
} | ||
const provider = new BrowserProvider(walletProvider, chainId) | ||
const amountToSend = parseGwei('0.001').toString(16) | ||
const calls = [ | ||
{ | ||
to: vitalikEthAddress as `0x${string}`, | ||
data: '0x' as `0x${string}`, | ||
value: `0x${amountToSend}` | ||
}, | ||
{ | ||
to: vitalikEthAddress as Address, | ||
value: '0x00', | ||
data: '0xdeadbeef' | ||
} | ||
] | ||
const sendCallsParams = { | ||
version: '1.0', | ||
chainId: `0x${BigInt(chainId).toString(16)}`, | ||
from: address, | ||
calls | ||
} | ||
const batchCallHash = await provider.send(EIP_5792_RPC_METHODS.WALLET_SEND_CALLS, [ | ||
sendCallsParams | ||
]) | ||
toast({ | ||
title: 'Success', | ||
description: batchCallHash, | ||
type: 'success' | ||
}) | ||
} catch { | ||
toast({ | ||
title: 'Error', | ||
description: 'Failed to send calls', | ||
type: 'error' | ||
}) | ||
} finally { | ||
setLoading(false) | ||
} | ||
} | ||
function isSendCallsSupported(): boolean { | ||
if (walletProvider instanceof EthereumProvider) { | ||
return Boolean( | ||
walletProvider?.signer?.session?.namespaces?.['eip155']?.methods?.includes( | ||
EIP_5792_RPC_METHODS.WALLET_SEND_CALLS | ||
) | ||
) | ||
} | ||
|
||
return false | ||
} | ||
|
||
if (!isConnected || !walletProvider || !address) { | ||
return ( | ||
<Text fontSize="md" color="yellow"> | ||
Wallet not connected | ||
</Text> | ||
) | ||
} | ||
if (!isSendCallsSupported()) { | ||
return ( | ||
<Text fontSize="md" color="yellow"> | ||
Wallet does not support wallet_sendCalls rpc | ||
</Text> | ||
) | ||
} | ||
if (atomicBatchSupportedChains.length === 0) { | ||
return ( | ||
<Text fontSize="md" color="yellow"> | ||
Account does not support atomic batch feature | ||
</Text> | ||
) | ||
} | ||
|
||
return currentChainsInfo ? ( | ||
<Stack direction={['column', 'column', 'row']}> | ||
<Button data-test-id="send-calls-button" onClick={onSendCalls} isDisabled={loading}> | ||
Send Batch Calls to Vitalik | ||
</Button> | ||
<Spacer /> | ||
</Stack> | ||
) : ( | ||
<Text fontSize="md" color="yellow"> | ||
Switch to {atomicBatchSupportedChainNames} to test atomic batch feature | ||
</Text> | ||
) | ||
} |
152 changes: 152 additions & 0 deletions
152
apps/laboratory/src/components/Ethers/EthersSendCallsWithPaymasterServiceTest.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
import { Button, Stack, Text, Input, Tooltip } from '@chakra-ui/react' | ||
import { useState } from 'react' | ||
import { useWeb3ModalAccount, useWeb3ModalProvider } from '@web3modal/ethers/react' | ||
import { EthereumProvider } from '@walletconnect/ethereum-provider' | ||
import { useChakraToast } from '../Toast' | ||
import { parseGwei } from 'viem' | ||
import { vitalikEthAddress } from '../../utils/DataUtil' | ||
import { BrowserProvider } from 'ethers' | ||
import { | ||
EIP_5792_RPC_METHODS, | ||
WALLET_CAPABILITIES, | ||
getCapabilitySupportedChainInfo | ||
} from '../../utils/EIP5792Utils' | ||
|
||
export function EthersSendCallsWithPaymasterServiceTest() { | ||
const [paymasterServiceUrl, setPaymasterServiceUrl] = useState<string>('') | ||
const [isLoading, setLoading] = useState(false) | ||
|
||
const { address, chainId, isConnected } = useWeb3ModalAccount() | ||
const { walletProvider } = useWeb3ModalProvider() | ||
const toast = useChakraToast() | ||
|
||
const paymasterServiceSupportedChains = | ||
address && walletProvider instanceof EthereumProvider | ||
? getCapabilitySupportedChainInfo( | ||
WALLET_CAPABILITIES.PAYMASTER_SERVICE, | ||
walletProvider, | ||
address | ||
) | ||
: [] | ||
const paymasterServiceSupportedChainNames = paymasterServiceSupportedChains | ||
.map(ci => ci.chainName) | ||
.join(', ') | ||
const currentChainsInfo = paymasterServiceSupportedChains.find( | ||
chainInfo => chainInfo.chainId === Number(chainId) | ||
) | ||
async function onSendCalls() { | ||
try { | ||
setLoading(true) | ||
if (!walletProvider || !address) { | ||
throw Error('user is disconnected') | ||
} | ||
if (!chainId) { | ||
throw Error('chain not selected') | ||
} | ||
|
||
if (!paymasterServiceUrl) { | ||
throw Error('paymasterServiceUrl not set') | ||
} | ||
const provider = new BrowserProvider(walletProvider, chainId) | ||
const amountToSend = parseGwei('0.001').toString(16) | ||
const calls = [ | ||
{ | ||
to: vitalikEthAddress, | ||
value: `0x${amountToSend}` | ||
}, | ||
{ | ||
to: vitalikEthAddress, | ||
data: '0xdeadbeef' | ||
} | ||
] | ||
const sendCallsParams = { | ||
version: '1.0', | ||
chainId: `0x${BigInt(chainId).toString(16)}`, | ||
from: address, | ||
calls, | ||
capabilities: { | ||
paymasterService: { | ||
url: paymasterServiceUrl | ||
} | ||
} | ||
} | ||
const batchCallHash = await provider.send(EIP_5792_RPC_METHODS.WALLET_SEND_CALLS, [ | ||
sendCallsParams | ||
]) | ||
toast({ | ||
title: 'SendCalls Success', | ||
description: batchCallHash, | ||
type: 'success' | ||
}) | ||
} catch { | ||
toast({ | ||
title: 'Error', | ||
description: 'Failed to send calls', | ||
type: 'error' | ||
}) | ||
} finally { | ||
setLoading(false) | ||
} | ||
} | ||
|
||
function isSendCallsSupported(): boolean { | ||
if (walletProvider instanceof EthereumProvider) { | ||
return Boolean( | ||
walletProvider?.signer?.session?.namespaces?.['eip155']?.methods?.includes( | ||
EIP_5792_RPC_METHODS.WALLET_SEND_CALLS | ||
) | ||
) | ||
} | ||
|
||
return false | ||
} | ||
|
||
if (!isConnected || !walletProvider || !address) { | ||
return ( | ||
<Text fontSize="md" color="yellow"> | ||
Wallet not connected | ||
</Text> | ||
) | ||
} | ||
if (!isSendCallsSupported()) { | ||
return ( | ||
<Text fontSize="md" color="yellow"> | ||
Wallet does not support wallet_sendCalls rpc | ||
</Text> | ||
) | ||
} | ||
if (paymasterServiceSupportedChains.length === 0) { | ||
return ( | ||
<Text fontSize="md" color="yellow"> | ||
Account does not support paymaster service feature | ||
</Text> | ||
) | ||
} | ||
|
||
return currentChainsInfo ? ( | ||
<Stack direction={['column', 'column', 'column']}> | ||
<Tooltip label="Paymaster Service URL should be of ERC-7677 paymaster service proxy"> | ||
<Input | ||
placeholder="http://api.pimlico.io/v2/sepolia/rpc?apikey=..." | ||
onChange={e => setPaymasterServiceUrl(e.target.value)} | ||
value={paymasterServiceUrl} | ||
isDisabled={isLoading} | ||
whiteSpace="nowrap" | ||
textOverflow="ellipsis" | ||
/> | ||
</Tooltip> | ||
<Button | ||
width={'fit-content'} | ||
data-test-id="send-calls-paymaster-service-button" | ||
onClick={onSendCalls} | ||
isDisabled={isLoading || !paymasterServiceUrl} | ||
> | ||
SendCalls w/ Paymaster Service | ||
</Button> | ||
</Stack> | ||
) : ( | ||
<Text fontSize="md" color="yellow"> | ||
Switch to {paymasterServiceSupportedChainNames} to test paymaster service feature | ||
</Text> | ||
) | ||
} |
Oops, something went wrong.