Skip to content

Commit

Permalink
feat: Counterfactual signing of smart accounts (reown-com#461)
Browse files Browse the repository at this point in the history
  • Loading branch information
Bacis authored Feb 9, 2024
1 parent 475847f commit 43d41d4
Show file tree
Hide file tree
Showing 13 changed files with 131 additions and 64 deletions.
2 changes: 1 addition & 1 deletion advanced/dapps/react-dapp-v2/.env.local.example
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
NEXT_PUBLIC_PROJECT_ID=39bc...
NEXT_PUBLIC_RELAY_URL=wss://relay.walletconnect.com
NEXT_PUBLIC_RELAY_URL=wss://relay.walletconnect.com
11 changes: 11 additions & 0 deletions advanced/dapps/react-dapp-v2/src/chains/eip155.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ export const EIP155ChainData: ChainsMap = {
slip44: 60,
testnet: true,
},
"11155111": {
name: "Ethereum Sepolia",
id: "eip155:11155111",
rpc: ["https://gateway.tenderly.co/public/sepolia "],
slip44: 60,
testnet: true,
},
"10": {
name: "Optimism Mainnet",
id: "eip155:10",
Expand Down Expand Up @@ -138,6 +145,10 @@ export const EIP155Metadata: NamespaceMetadata = {
logo: "/assets/" + "eip155-1.png",
rgb: EIP155Colors.ethereum,
},
"11155111": {
logo: "/assets/" + "eip155-1.png",
rgb: EIP155Colors.ethereum,
},
"10": {
name: "Optimism",
logo: "/assets/" + "eip155-10.png",
Expand Down
1 change: 1 addition & 0 deletions advanced/dapps/react-dapp-v2/src/constants/default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const DEFAULT_MAIN_CHAINS = [
export const DEFAULT_TEST_CHAINS = [
// testnets
"eip155:5",
"eip155:11155111",
"eip155:280",
"eip155:420",
"eip155:80001",
Expand Down
8 changes: 8 additions & 0 deletions advanced/dapps/react-dapp-v2/src/helpers/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ export const rpcProvidersByChainId: RpcProvidersByChainId = {
symbol: "ETH",
},
},
11155111: {
name: "Ethereum Sepolia",
baseURL: WALLETCONNECT_RPC_BASE_URL + "&chainId=eip155:11155111",
token: {
name: "Ether",
symbol: "ETH",
},
},
137: {
name: "Polygon Mainnet",
baseURL: WALLETCONNECT_RPC_BASE_URL + "&chainId=eip155:137",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ interface Props {
}

export default function ChainAddressMini({ address }: Props) {
if (!address) return <></>
if (!address || address === 'N/A') return <></>
return (
<>
<Row>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@ import ChainAddressMini from './ChainAddressMini'
import { createOrRestoreEIP155Wallet, eip155Wallets } from '@/utils/EIP155WalletUtil'
import { Spinner } from '@nextui-org/react'
import { Chain, allowedChains } from '@/utils/SmartAccountUtils'
import { useSnapshot } from 'valtio'
import SettingsStore from '@/store/SettingsStore'

interface Props {
namespace: string
chain: {
chainId: string;
name: string;
logo: string;
rgb: string;
namespace: string;
} | undefined
}

const getKey = (namespace?: string) => {
Expand All @@ -20,10 +24,11 @@ const getKey = (namespace?: string) => {
}
}

export default function ChainSmartAddressMini({ namespace }: Props) {
const { activeChainId } = useSnapshot(SettingsStore.state)
const { address } = useSmartAccount(getKey(namespace) as `0x${string}`, allowedChains.find((c) => c.id.toString() === activeChainId) as Chain)

export default function ChainSmartAddressMini({chain}: Props) {
const { address } = useSmartAccount(
getKey(chain?.namespace) as `0x${string}`,
allowedChains.find((c) => c.id.toString() === chain?.chainId.toString()) as Chain
)
if (!address) return <Spinner />
return (
<ChainAddressMini address={address}/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,6 @@ export default function SmartAccountCard({
setTimeout(() => setCopied(false), 1500)
}

async function onChainChanged(chainId: string, address: string) {
SettingsStore.setActiveChainId(chainId)
await updateSignClientChainId(chainId.toString(), address)
}

async function onCreateSmartAccount() {
try {
if (!isDeployed) {
Expand All @@ -58,6 +53,11 @@ export default function SmartAccountCard({
console.error(error)
}
}

async function onChainChanged(chainId: string, address: string) {
SettingsStore.setActiveChainId(chainId)
await updateSignClientChainId(chainId.toString(), address)
}

return (
<ChainCard rgb={rgb} flexDirection="row" alignItems="center" flexWrap="wrap">
Expand Down
2 changes: 1 addition & 1 deletion advanced/wallets/react-wallet-v2/src/data/EIP155Data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export const EIP155_TEST_CHAINS: Record<string,EIP155Chain> = {
name: 'Ethereum Sepolia',
logo: '/chain-logos/eip155-1.png',
rgb: '99, 125, 234',
rpc: 'https://rpc.sepolia.org',
rpc: 'https://gateway.tenderly.co/public/sepolia',
namespace: 'eip155',
smartAccountEnabled: true,
},
Expand Down
21 changes: 10 additions & 11 deletions advanced/wallets/react-wallet-v2/src/hooks/useSmartAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useSnapshot } from "valtio";
import { Hex } from "viem";
import { styledToast } from "@/utils/HelperUtil";
import { TransactionExecutionError } from "viem";
import { SmartAccount } from "permissionless/accounts";

export default function useSmartAccount(signerPrivateKey: Hex, chain: Chain) {
const [loading, setLoading] = useState(false)
Expand Down Expand Up @@ -33,11 +34,6 @@ export default function useSmartAccount(signerPrivateKey: Hex, chain: Chain) {
}
}, [setLoading])

const deploy = useCallback(async () => {
if (!client) return
execute(client?.deploySmartAccount)
}, [client, execute])

const sendTestTransaction = useCallback(async () => {
if (!client) return
execute(() => client?.sendTransaction({
Expand All @@ -47,6 +43,11 @@ export default function useSmartAccount(signerPrivateKey: Hex, chain: Chain) {
}))
}, [client, execute])

const deploy = useCallback(async () => {
if (!client) return
execute(client?.deploySmartAccount)
}, [client, execute])

useEffect(() => {
if (!signerPrivateKey || !chain) return
const smartAccountClient = new SmartAccountLib({
Expand All @@ -58,19 +59,17 @@ export default function useSmartAccount(signerPrivateKey: Hex, chain: Chain) {
}, [signerPrivateKey, smartAccountSponsorshipEnabled, chain])

useEffect(() => {
client?.init()
.then(() => {
setIsDeployed(client?.isDeployed)
setAddress(client?.address)
client?.getAccount()
.then((account: SmartAccount) => {
setAddress(account.address)
})
}, [client, chain])


return {
address,
isDeployed,
deploy,
loading,
sendTestTransaction,
deploy
}
}
2 changes: 2 additions & 0 deletions advanced/wallets/react-wallet-v2/src/lib/SmartAccountLib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ export class SmartAccountLib {
throw new Error('A Pimlico API Key is required')
}

console.log('investigate 2', chain, privateKey, sponsored)

this.chain = chain
this.sponsored = sponsored
this.#signerPrivateKey = privateKey
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@ import { formatJsonRpcError, formatJsonRpcResult } from '@json-rpc-tools/utils'
import { SignClientTypes } from '@walletconnect/types'
import { getSdkError } from '@walletconnect/utils'
import { providers } from 'ethers'
import { chains } from './SmartAccountUtils'
import { Hex } from 'viem'
import { Chain, allowedChains } from './SmartAccountUtils'
import SettingsStore from '@/store/SettingsStore'
type RequestEventArgs = Omit<SignClientTypes.EventArguments['session_request'], 'verifyContext'>


const getWallet = async (params: any) => {
const typedChains: Record<number, Chain> = chains;
console.log('get wallet params', params)
const chainId = params?.chainId?.split(':')[1]
console.log('chain id', chainId)
Expand All @@ -28,12 +31,18 @@ const getWallet = async (params: any) => {
const smartAccountEnabledChain = allowedChains.find((chain) => chain.id.toString() === chainId) as Chain
console.log('smart account enabled chain', smartAccountEnabledChain)
const smartAccounts = await Promise.all(Object.values(eip155Wallets).map(async (wallet) => {
console.log('typeed chains', typedChains[chainId])

const smartAccount = new SmartAccountLib({
privateKey: wallet.getPrivateKey() as Hex,
chain: smartAccountEnabledChain,
chain: typedChains[chainId],
sponsored: true, // TODO: Sponsor for now but should be dynamic according to SettingsStore
})
await smartAccount.init()

const isDeployed = await smartAccount.checkIfSmartAccountDeployed()
if (!isDeployed) {
await smartAccount.deploySmartAccount()
}
return smartAccount
}));

Expand All @@ -46,6 +55,11 @@ const getWallet = async (params: any) => {
export async function approveEIP155Request(requestEvent: RequestEventArgs) {
const { params, id } = requestEvent
const { chainId, request } = params

console.log(requestEvent, chainId, "tests")

SettingsStore.setActiveChainId(chainId)

const wallet = await getWallet(params)

switch (request.method) {
Expand Down
11 changes: 10 additions & 1 deletion advanced/wallets/react-wallet-v2/src/utils/SmartAccountUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ const apiKey = process.env.NEXT_PUBLIC_PIMLICO_KEY

// Types
export const allowedChains = [sepolia, polygonMumbai, goerli] as const
// build chains so I can access them by id
export const chains = allowedChains.reduce((acc, chain) => {
acc[chain.id] = chain
return acc
}, {} as Record<Chain['id'], Chain>)
export type Chain = (typeof allowedChains)[number]
export type UrlConfig = {
chain: Chain
Expand Down Expand Up @@ -56,7 +61,11 @@ export const USDC_FAUCET_URL = 'https://faucet.circle.com/'

export const VITALIK_ADDRESS = '0xd8da6bf26964af9d7eed9e03e53415d37aa96045' as Hex

export const publicRPCUrl = ({ chain }: UrlConfig) => RPC_URLS[chain.name]
export const publicRPCUrl = ({ chain }: UrlConfig) => {
console.log("investigate", chain)
return RPC_URLS[chain?.name]
}

export const paymasterUrl = ({ chain }: UrlConfig) =>
`https://api.pimlico.io/v2/${PIMLICO_NETWORK_NAMES[chain.name]}/rpc?apikey=${apiKey}`
export const bundlerUrl = ({ chain }: UrlConfig) =>
Expand Down
Loading

0 comments on commit 43d41d4

Please sign in to comment.