|
1 | | -import { createClient, type FallbackTransport, type HttpTransport, type Transport } from 'viem' |
| 1 | +import { |
| 2 | + createClient, |
| 3 | + formatTransactionRequest, |
| 4 | + type ExactPartial, |
| 5 | + type FallbackTransport, |
| 6 | + type HttpTransport, |
| 7 | + type TransactionRequest, |
| 8 | + type TransactionType, |
| 9 | + type Transport, |
| 10 | +} from 'viem' |
2 | 11 | import { createConfig, createStorage, fallback, http } from 'wagmi' |
3 | 12 | import { holesky, localhost, mainnet, sepolia } from 'wagmi/chains' |
4 | 13 |
|
@@ -87,7 +96,51 @@ export const transports = { |
87 | 96 | [holesky.id]: initialiseTransports('holesky', [drpcUrl, tenderlyUrl]), |
88 | 97 | } as const |
89 | 98 |
|
90 | | -const chains = getChainsFromUrl() as unknown as readonly [SupportedChain, ...SupportedChain[]] |
| 99 | +// This is a workaround to fix MetaMask defaulting to the wrong transaction type |
| 100 | +// when no type is specified, but an access list is provided. |
| 101 | +// See: https://github.com/MetaMask/core/issues/5720 |
| 102 | +// Viem by default doesn't include the type in a TransactionRequest, because it's generally not required. |
| 103 | +// To fix the MetaMask issue, we need to include it. However, we don't want to break other wallets, so we only add it |
| 104 | +// for MetaMask. |
| 105 | +// Viem will use a chain specific transactionRequest formatter if provided, so we can utilise this to |
| 106 | +// add `type`. |
| 107 | +// References to the formatter are: |
| 108 | +// 1. Call to `extract` with all extra parameters (i.e. unused by call by default), and the chain specific formatter |
| 109 | +// a. If a formatter is not provided, the function returns `{}` (existing behaviour) |
| 110 | +// b. If a formatter is provided, returns the formatted extra parameters |
| 111 | +// 2. Call to chain specific formatter if provided, otherwise `formatTransactionRequest`, with the request and the formatted extra parameters |
| 112 | +// |
| 113 | +// We want to capture only the first call, so `type` is added to the final request object without |
| 114 | +// modifying existing behaviour. |
| 115 | +const formatExtraTransactionRequestParameters = ( |
| 116 | + request: |
| 117 | + | { type: TransactionType } |
| 118 | + // eslint-disable-next-line @typescript-eslint/naming-convention |
| 119 | + | { type: TransactionType; __is_metamask: boolean } |
| 120 | + | ExactPartial<TransactionRequest>, |
| 121 | +) => { |
| 122 | + // 1: Call will never have `from` |
| 123 | + if (!('from' in request)) { |
| 124 | + // 1a: Default behaviour when not MetaMask |
| 125 | + if (!('__is_metamask' in request) || !request.__is_metamask) return {} |
| 126 | + // 1b: Add `type` to the request |
| 127 | + return { |
| 128 | + type: request.type, |
| 129 | + } |
| 130 | + } |
| 131 | + // 2: Standard call to formatter |
| 132 | + return formatTransactionRequest(request) |
| 133 | +} |
| 134 | + |
| 135 | +const chains = getChainsFromUrl().map((c) => ({ |
| 136 | + ...c, |
| 137 | + formatters: { |
| 138 | + ...(c.formatters || {}), |
| 139 | + transactionRequest: { |
| 140 | + format: formatExtraTransactionRequestParameters, |
| 141 | + }, |
| 142 | + }, |
| 143 | +})) as unknown as readonly [SupportedChain, ...SupportedChain[]] |
91 | 144 |
|
92 | 145 | const wagmiConfig_ = createConfig({ |
93 | 146 | syncConnectedChain: false, |
|
0 commit comments