From ab4dc6f57a0f1198cd83062f04ac932e56c731c0 Mon Sep 17 00:00:00 2001 From: Leon Talbert Date: Fri, 13 Dec 2024 16:52:02 +0800 Subject: [PATCH] Capsule priority fee --- src/components/@atoms/BaseLink.tsx | 11 +++++++- .../stage/TransactionStageModal.tsx | 6 +++-- .../TransactionDialogManager/stage/query.ts | 26 ++++++++++++++++++- src/components/ConnectButton.tsx | 16 +++++++----- src/constants/chains.ts | 11 ++++---- src/utils/utils.ts | 5 ++++ 6 files changed, 60 insertions(+), 15 deletions(-) diff --git a/src/components/@atoms/BaseLink.tsx b/src/components/@atoms/BaseLink.tsx index 29a634c0a..41b5c547d 100644 --- a/src/components/@atoms/BaseLink.tsx +++ b/src/components/@atoms/BaseLink.tsx @@ -26,7 +26,16 @@ export const BaseLinkWithHistory = ({ return getDestination({ pathname: href, query: initialQuery }) as UrlObject }, [href, router.asPath]) - return + return ( + + ) } export default BaseLink diff --git a/src/components/@molecules/TransactionDialogManager/stage/TransactionStageModal.tsx b/src/components/@molecules/TransactionDialogManager/stage/TransactionStageModal.tsx index d06a5b9b3..96f54baa4 100644 --- a/src/components/@molecules/TransactionDialogManager/stage/TransactionStageModal.tsx +++ b/src/components/@molecules/TransactionDialogManager/stage/TransactionStageModal.tsx @@ -5,7 +5,7 @@ import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' import { match, P } from 'ts-pattern' import { BaseError } from 'viem' -import { useClient, useConnectorClient, useSendTransaction } from 'wagmi' +import { useClient, useConnections, useConnectorClient, useSendTransaction } from 'wagmi' import { Button, @@ -395,9 +395,11 @@ export const TransactionStageModal = ({ queryFn: createTransactionRequestQueryFn, }) + const connections = useConnections() + const preparedOptions = queryOptions({ queryKey: initialOptions.queryKey, - queryFn: initialOptions.queryFn({ connectorClient, isSafeApp }), + queryFn: initialOptions.queryFn({ connectorClient, isSafeApp, connections }), }) const transactionRequestQuery = useQuery({ diff --git a/src/components/@molecules/TransactionDialogManager/stage/query.ts b/src/components/@molecules/TransactionDialogManager/stage/query.ts index 12da54e6e..f8b0bc80e 100644 --- a/src/components/@molecules/TransactionDialogManager/stage/query.ts +++ b/src/components/@molecules/TransactionDialogManager/stage/query.ts @@ -1,5 +1,5 @@ import { QueryFunctionContext } from '@tanstack/react-query' -import { CallParameters, SendTransactionReturnType } from '@wagmi/core' +import { CallParameters, getFeeHistory, SendTransactionReturnType } from '@wagmi/core' import { Dispatch } from 'react' import { Address, @@ -32,7 +32,9 @@ import { CreateQueryKey, } from '@app/types' import { getReadableError } from '@app/utils/errors' +import { wagmiConfig } from '@app/utils/query/wagmi' import { CheckIsSafeAppReturnType } from '@app/utils/safe' +import { hasCapsuleConnection } from '@app/utils/utils' type AccessListResponse = { accessList: { @@ -161,6 +163,19 @@ export const calculateGasLimit = async ({ } } +const getLargestMedianGasFee = async () => { + const feeHistory = await getFeeHistory(wagmiConfig, { + blockCount: 5, + rewardPercentiles: [50], + }) + + const maxPriorityFeePerGas = feeHistory.reward + .map((block) => block[0]) + .reduce((max, fee) => (fee > max ? fee : max), BigInt(0)) + + return maxPriorityFeePerGas +} + export type CreateTransactionRequestQueryKey = CreateQueryKey< UniqueTransaction, 'createTransactionRequest', @@ -181,6 +196,7 @@ export const createTransactionRequestUnsafe = async ({ isSafeApp, params, chainId, + connections, }: CreateTransactionRequestUnsafeParameters) => { const transactionRequest = await createTransactionRequest({ name: params.name, @@ -203,6 +219,10 @@ export const createTransactionRequestUnsafe = async ({ transactionName: params.name, }) + const isCapsuleConnected = hasCapsuleConnection(connections) + + const largestMedianGasFee = await getLargestMedianGasFee() + const request = await prepareTransactionRequest(client, { to: transactionRequest.to, accessList, @@ -211,6 +231,7 @@ export const createTransactionRequestUnsafe = async ({ gas: gasLimit, parameters: ['fees', 'nonce', 'type'], ...('value' in transactionRequest ? { value: transactionRequest.value } : {}), + ...(isCapsuleConnected ? { maxPriorityFeePerGas: largestMedianGasFee } : {}), }) return { @@ -227,9 +248,11 @@ export const createTransactionRequestQueryFn = ({ connectorClient, isSafeApp, + connections, }: { connectorClient: ConnectorClientWithEns | undefined isSafeApp: CheckIsSafeAppReturnType | undefined + connections: any }) => async ({ queryKey: [params, chainId, address], @@ -248,6 +271,7 @@ export const createTransactionRequestQueryFn = isSafeApp, params, chainId, + connections, }), error: null, } diff --git a/src/components/ConnectButton.tsx b/src/components/ConnectButton.tsx index 864f40267..6452113f8 100644 --- a/src/components/ConnectButton.tsx +++ b/src/components/ConnectButton.tsx @@ -26,7 +26,7 @@ import { useRouterWithHistory } from '@app/hooks/useRouterWithHistory' import { useZorb } from '@app/hooks/useZorb' import { useBreakpoint } from '@app/utils/BreakpointProvider' import { ensAvatarConfig } from '@app/utils/query/ipfsGateway' -import { shortenAddress } from '@app/utils/utils' +import { hasCapsuleConnection, shortenAddress } from '@app/utils/utils' import BaseLink from './@atoms/BaseLink' @@ -147,9 +147,7 @@ const HeaderProfile = ({ address }: { address: Address }) => { const hasPendingTransactions = useHasPendingTransactions() const connections = useConnections() - const isCapsuleConnected = connections.some( - (connection) => connection?.connector?.id === 'capsule-integrated', - ) + const isCapsuleConnected = hasCapsuleConnection(connections) return ( { color: 'text', icon: , wrapper: (children: ReactNode, key: Key) => ( - + {children} - + ), }, ] diff --git a/src/constants/chains.ts b/src/constants/chains.ts index 9316bf212..56edd7ae4 100644 --- a/src/constants/chains.ts +++ b/src/constants/chains.ts @@ -48,13 +48,14 @@ export type SupportedChain = | typeof localhostWithEns export const getChainsFromUrl = () => { - if (typeof window === 'undefined') + if (typeof window === 'undefined') { return [ ...(isLocalProvider ? ([localhostWithEns] as const) : ([] as const)), sepoliaWithEns, mainnetWithEns, holeskyWithEns, ] + } const { hostname, search } = window.location const params = new URLSearchParams(search) @@ -62,12 +63,12 @@ export const getChainsFromUrl = () => { const segments = hostname.split('.') if (segments.length === 4 && segments.slice(1).join('.') === 'ens-app-v3.pages.dev') { - if (chainParam === 'sepolia') return sepoliaWithEns - if (chainParam === 'holesky') return holeskyWithEns + if (chainParam === 'sepolia') return [sepoliaWithEns, mainnetWithEns, holeskyWithEns] + if (chainParam === 'holesky') return [holeskyWithEns, sepoliaWithEns, mainnetWithEns] } - if (!hostname.includes('app.ens.domains')) return mainnetWithEns - if (segments.length !== 4) return mainnetWithEns + if (!hostname.includes('app.ens.domains')) return [mainnetWithEns, holeskyWithEns, sepoliaWithEns] + if (segments.length !== 4) return [mainnetWithEns, holeskyWithEns, sepoliaWithEns] return match(segments[0]) .with('sepolia', () => [ diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 13c41f7d6..3e6a233cd 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -1,5 +1,6 @@ import type { TFunction } from 'react-i18next' import { toBytes, type Address } from 'viem' +import { Connection } from 'wagmi' import { Eth2ldName } from '@ensdomains/ensjs/dist/types/types' import { GetPriceReturnType } from '@ensdomains/ensjs/public' @@ -220,3 +221,7 @@ export const hslToHex = (hsl: string) => { } return `#${f(0)}${f(8)}${f(4)}` } + +export const hasCapsuleConnection = (connections: Connection[]) => { + return connections.some((connection) => connection?.connector?.id === 'capsule-integrated') +}