viem 2.55.16 → 2.55.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/_cjs/actions/public/fillTransaction.js +45 -35
- package/_cjs/actions/public/fillTransaction.js.map +1 -1
- package/_cjs/actions/wallet/prepareTransactionRequest.js +4 -0
- package/_cjs/actions/wallet/prepareTransactionRequest.js.map +1 -1
- package/_cjs/chains/definitions/hausTestnet.js +27 -0
- package/_cjs/chains/definitions/hausTestnet.js.map +1 -0
- package/_cjs/chains/index.js +12 -10
- package/_cjs/chains/index.js.map +1 -1
- package/_cjs/errors/transaction.js +13 -1
- package/_cjs/errors/transaction.js.map +1 -1
- package/_cjs/errors/version.js +1 -1
- package/_cjs/index.js +5 -4
- package/_cjs/index.js.map +1 -1
- package/_cjs/op-stack/abis.js +14 -0
- package/_cjs/op-stack/abis.js.map +1 -1
- package/_cjs/op-stack/actions/estimateOperatorFee.js +26 -15
- package/_cjs/op-stack/actions/estimateOperatorFee.js.map +1 -1
- package/_esm/actions/public/fillTransaction.js +49 -36
- package/_esm/actions/public/fillTransaction.js.map +1 -1
- package/_esm/actions/wallet/prepareTransactionRequest.js +4 -0
- package/_esm/actions/wallet/prepareTransactionRequest.js.map +1 -1
- package/_esm/chains/definitions/hausTestnet.js +24 -0
- package/_esm/chains/definitions/hausTestnet.js.map +1 -0
- package/_esm/chains/index.js +1 -0
- package/_esm/chains/index.js.map +1 -1
- package/_esm/errors/transaction.js +11 -0
- package/_esm/errors/transaction.js.map +1 -1
- package/_esm/errors/version.js +1 -1
- package/_esm/index.js +1 -1
- package/_esm/index.js.map +1 -1
- package/_esm/op-stack/abis.js +14 -0
- package/_esm/op-stack/abis.js.map +1 -1
- package/_esm/op-stack/actions/estimateOperatorFee.js +28 -25
- package/_esm/op-stack/actions/estimateOperatorFee.js.map +1 -1
- package/_types/actions/public/fillTransaction.d.ts.map +1 -1
- package/_types/actions/wallet/prepareTransactionRequest.d.ts.map +1 -1
- package/_types/chains/definitions/hausTestnet.d.ts +52 -0
- package/_types/chains/definitions/hausTestnet.d.ts.map +1 -0
- package/_types/chains/index.d.ts +1 -0
- package/_types/chains/index.d.ts.map +1 -1
- package/_types/errors/transaction.d.ts +9 -0
- package/_types/errors/transaction.d.ts.map +1 -1
- package/_types/errors/version.d.ts +1 -1
- package/_types/index.d.ts +1 -1
- package/_types/index.d.ts.map +1 -1
- package/_types/op-stack/abis.d.ts +24 -0
- package/_types/op-stack/abis.d.ts.map +1 -1
- package/_types/op-stack/actions/estimateOperatorFee.d.ts +6 -2
- package/_types/op-stack/actions/estimateOperatorFee.d.ts.map +1 -1
- package/actions/public/fillTransaction.ts +53 -35
- package/actions/wallet/prepareTransactionRequest.ts +6 -0
- package/chains/definitions/hausTestnet.ts +24 -0
- package/chains/index.ts +1 -0
- package/errors/transaction.ts +21 -0
- package/errors/version.ts +1 -1
- package/index.ts +2 -0
- package/op-stack/abis.ts +14 -0
- package/op-stack/actions/estimateOperatorFee.ts +50 -36
- package/package.json +1 -1
|
@@ -4,6 +4,7 @@ import type { Client } from '../../clients/createClient.js'
|
|
|
4
4
|
import type { Transport } from '../../clients/transports/createTransport.js'
|
|
5
5
|
import type { BaseError } from '../../errors/base.js'
|
|
6
6
|
import { BaseFeeScalarError } from '../../errors/fee.js'
|
|
7
|
+
import { FeePayerNonceMismatchError } from '../../errors/transaction.js'
|
|
7
8
|
import type { ErrorType } from '../../errors/utils.js'
|
|
8
9
|
import type { Account, GetAccountParameter } from '../../types/account.js'
|
|
9
10
|
import type { ExtractCapabilities } from '../../types/capabilities.js'
|
|
@@ -194,44 +195,61 @@ export async function fillTransaction<
|
|
|
194
195
|
// Rewrite fields.
|
|
195
196
|
transaction.data = transaction.input
|
|
196
197
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
transaction.gasPrice = parameters.gasPrice ?? transaction.gasPrice
|
|
201
|
-
if (transaction.maxFeePerBlobGas)
|
|
202
|
-
transaction.maxFeePerBlobGas =
|
|
203
|
-
parameters.maxFeePerBlobGas ?? transaction.maxFeePerBlobGas
|
|
204
|
-
if (transaction.maxFeePerGas)
|
|
205
|
-
transaction.maxFeePerGas =
|
|
206
|
-
parameters.maxFeePerGas ?? transaction.maxFeePerGas
|
|
207
|
-
if (transaction.maxPriorityFeePerGas)
|
|
208
|
-
transaction.maxPriorityFeePerGas =
|
|
209
|
-
parameters.maxPriorityFeePerGas ?? transaction.maxPriorityFeePerGas
|
|
210
|
-
if (typeof transaction.nonce !== 'undefined')
|
|
211
|
-
transaction.nonce = parameters.nonce ?? transaction.nonce
|
|
198
|
+
const hasFeePayerSignature =
|
|
199
|
+
typeof transaction.feePayerSignature !== 'undefined' &&
|
|
200
|
+
transaction.feePayerSignature !== null
|
|
212
201
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
202
|
+
if (
|
|
203
|
+
hasFeePayerSignature &&
|
|
204
|
+
typeof nonce !== 'undefined' &&
|
|
205
|
+
transaction.nonce !== nonce
|
|
206
|
+
)
|
|
207
|
+
throw new FeePayerNonceMismatchError({
|
|
208
|
+
filledNonce: transaction.nonce,
|
|
209
|
+
requestedNonce: nonce,
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
// A fee payer signature commits to the filled transaction, so preserve
|
|
213
|
+
// its signed fields regardless of who produced the signature.
|
|
214
|
+
// https://tips.sh/0001#fee-payer-signature
|
|
215
|
+
if (!hasFeePayerSignature) {
|
|
216
|
+
// Preference supplied fees (some nodes do not take these preferences).
|
|
217
|
+
if (transaction.gas) transaction.gas = parameters.gas ?? transaction.gas
|
|
218
|
+
if (transaction.gasPrice)
|
|
219
|
+
transaction.gasPrice = parameters.gasPrice ?? transaction.gasPrice
|
|
220
|
+
if (transaction.maxFeePerBlobGas)
|
|
221
|
+
transaction.maxFeePerBlobGas =
|
|
222
|
+
parameters.maxFeePerBlobGas ?? transaction.maxFeePerBlobGas
|
|
223
|
+
if (transaction.maxFeePerGas)
|
|
224
|
+
transaction.maxFeePerGas =
|
|
225
|
+
parameters.maxFeePerGas ?? transaction.maxFeePerGas
|
|
226
|
+
if (transaction.maxPriorityFeePerGas)
|
|
227
|
+
transaction.maxPriorityFeePerGas =
|
|
228
|
+
parameters.maxPriorityFeePerGas ?? transaction.maxPriorityFeePerGas
|
|
229
|
+
if (typeof transaction.nonce !== 'undefined')
|
|
230
|
+
transaction.nonce = parameters.nonce ?? transaction.nonce
|
|
231
|
+
|
|
232
|
+
// Build fee multiplier function.
|
|
233
|
+
const feeMultiplier = await (async () => {
|
|
234
|
+
if (typeof chain?.fees?.baseFeeMultiplier === 'function') {
|
|
235
|
+
const block = await getAction(client, getBlock, 'getBlock')({})
|
|
236
|
+
return chain.fees.baseFeeMultiplier({
|
|
237
|
+
block,
|
|
238
|
+
client,
|
|
239
|
+
request: parameters,
|
|
240
|
+
} as ChainFeesFnParameters)
|
|
241
|
+
}
|
|
242
|
+
return chain?.fees?.baseFeeMultiplier ?? 1.2
|
|
243
|
+
})()
|
|
244
|
+
if (feeMultiplier < 1) throw new BaseFeeScalarError()
|
|
226
245
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
246
|
+
const decimals = feeMultiplier.toString().split('.')[1]?.length ?? 0
|
|
247
|
+
const denominator = 10 ** decimals
|
|
248
|
+
const multiplyFee = (base: bigint) =>
|
|
249
|
+
(base * BigInt(Math.round(feeMultiplier * denominator))) /
|
|
250
|
+
BigInt(denominator)
|
|
232
251
|
|
|
233
|
-
|
|
234
|
-
if (!transaction.feePayerSignature) {
|
|
252
|
+
// Apply fee multiplier.
|
|
235
253
|
if (transaction.maxFeePerGas && !parameters.maxFeePerGas)
|
|
236
254
|
transaction.maxFeePerGas = multiplyFee(transaction.maxFeePerGas)
|
|
237
255
|
if (transaction.gasPrice && !parameters.gasPrice)
|
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
Eip1559FeesNotSupportedError,
|
|
30
30
|
MaxFeePerGasTooLowError,
|
|
31
31
|
} from '../../errors/fee.js'
|
|
32
|
+
import { FeePayerNonceMismatchError } from '../../errors/transaction.js'
|
|
32
33
|
import type { DeriveAccount, GetAccountParameter } from '../../types/account.js'
|
|
33
34
|
import type { Block } from '../../types/block.js'
|
|
34
35
|
import type { ExtractCapabilities } from '../../types/capabilities.js'
|
|
@@ -509,6 +510,11 @@ export async function prepareTransactionRequest<
|
|
|
509
510
|
|
|
510
511
|
if (error.name !== 'TransactionExecutionError') return request
|
|
511
512
|
|
|
513
|
+
const nonceMismatch = error.walk?.(
|
|
514
|
+
(error) => error instanceof FeePayerNonceMismatchError,
|
|
515
|
+
)
|
|
516
|
+
if (nonceMismatch) throw e
|
|
517
|
+
|
|
512
518
|
const executionReverted = error.walk?.((e) => {
|
|
513
519
|
const error = e as BaseError
|
|
514
520
|
return error.name === 'ExecutionRevertedError'
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { defineChain } from '../../utils/chain/defineChain.js'
|
|
2
|
+
|
|
3
|
+
export const hausTestnet = /*#__PURE__*/ defineChain({
|
|
4
|
+
id: 2_443,
|
|
5
|
+
name: 'Haus Chain Testnet',
|
|
6
|
+
nativeCurrency: {
|
|
7
|
+
decimals: 18,
|
|
8
|
+
name: 'Haus',
|
|
9
|
+
symbol: 'HAUS',
|
|
10
|
+
},
|
|
11
|
+
rpcUrls: {
|
|
12
|
+
default: {
|
|
13
|
+
http: ['https://rpc-testnet.hausserver.xyz'],
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
blockExplorers: {
|
|
17
|
+
default: {
|
|
18
|
+
name: 'Haus Chain Testnet Explorer',
|
|
19
|
+
url: 'https://explorer-testnet.hausserver.xyz',
|
|
20
|
+
apiUrl: 'https://explorer-testnet.hausserver.xyz/api',
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
testnet: true,
|
|
24
|
+
})
|
package/chains/index.ts
CHANGED
|
@@ -267,6 +267,7 @@ export { hardhat } from './definitions/hardhat.js'
|
|
|
267
267
|
export { harmonyOne } from './definitions/harmonyOne.js'
|
|
268
268
|
export { hashkey } from './definitions/hashKeyChain.js'
|
|
269
269
|
export { hashkeyTestnet } from './definitions/hashkeyChainTestnet.js'
|
|
270
|
+
export { hausTestnet } from './definitions/hausTestnet.js'
|
|
270
271
|
export { haustTestnet } from './definitions/haustTestnet.js'
|
|
271
272
|
export { hedera } from './definitions/hedera.js'
|
|
272
273
|
export { hederaPreviewnet } from './definitions/hederaPreviewnet.js'
|
package/errors/transaction.ts
CHANGED
|
@@ -42,6 +42,27 @@ export class FeeConflictError extends BaseError {
|
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
export type FeePayerNonceMismatchErrorType = FeePayerNonceMismatchError & {
|
|
46
|
+
name: 'FeePayerNonceMismatchError'
|
|
47
|
+
}
|
|
48
|
+
export class FeePayerNonceMismatchError extends BaseError {
|
|
49
|
+
constructor({
|
|
50
|
+
filledNonce,
|
|
51
|
+
requestedNonce,
|
|
52
|
+
}: {
|
|
53
|
+
filledNonce: number | undefined
|
|
54
|
+
requestedNonce: number
|
|
55
|
+
}) {
|
|
56
|
+
super('The filled transaction nonce does not match the requested nonce.', {
|
|
57
|
+
metaMessages: [
|
|
58
|
+
`Requested Nonce: ${requestedNonce}`,
|
|
59
|
+
`Filled Nonce: ${filledNonce}`,
|
|
60
|
+
],
|
|
61
|
+
name: 'FeePayerNonceMismatchError',
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
45
66
|
export type InvalidLegacyVErrorType = InvalidLegacyVError & {
|
|
46
67
|
name: 'InvalidLegacyVError'
|
|
47
68
|
}
|
package/errors/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '2.55.
|
|
1
|
+
export const version = '2.55.17'
|
package/index.ts
CHANGED
|
@@ -1036,6 +1036,8 @@ export {
|
|
|
1036
1036
|
export {
|
|
1037
1037
|
FeeConflictError,
|
|
1038
1038
|
type FeeConflictErrorType,
|
|
1039
|
+
FeePayerNonceMismatchError,
|
|
1040
|
+
type FeePayerNonceMismatchErrorType,
|
|
1039
1041
|
InvalidLegacyVError,
|
|
1040
1042
|
type InvalidLegacyVErrorType,
|
|
1041
1043
|
InvalidSerializableTransactionError,
|
package/op-stack/abis.ts
CHANGED
|
@@ -46,6 +46,20 @@ export const gasPriceOracleAbi = [
|
|
|
46
46
|
stateMutability: 'view',
|
|
47
47
|
type: 'function',
|
|
48
48
|
},
|
|
49
|
+
{
|
|
50
|
+
inputs: [{ internalType: 'uint256', name: '_gasUsed', type: 'uint256' }],
|
|
51
|
+
name: 'getOperatorFee',
|
|
52
|
+
outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
|
|
53
|
+
stateMutability: 'view',
|
|
54
|
+
type: 'function',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
inputs: [],
|
|
58
|
+
name: 'isJovian',
|
|
59
|
+
outputs: [{ internalType: 'bool', name: '', type: 'bool' }],
|
|
60
|
+
stateMutability: 'view',
|
|
61
|
+
type: 'function',
|
|
62
|
+
},
|
|
49
63
|
{
|
|
50
64
|
inputs: [],
|
|
51
65
|
name: 'l1BaseFee',
|
|
@@ -18,7 +18,7 @@ import type { TransactionRequestEIP1559 } from '../../types/transaction.js'
|
|
|
18
18
|
import type { RequestErrorType } from '../../utils/buildRequest.js'
|
|
19
19
|
import { getChainContractAddress } from '../../utils/chain/getChainContractAddress.js'
|
|
20
20
|
import type { HexToNumberErrorType } from '../../utils/encoding/fromHex.js'
|
|
21
|
-
import { l1BlockAbi } from '../abis.js'
|
|
21
|
+
import { gasPriceOracleAbi, l1BlockAbi } from '../abis.js'
|
|
22
22
|
import { contracts } from '../contracts.js'
|
|
23
23
|
|
|
24
24
|
export type EstimateOperatorFeeParameters<
|
|
@@ -28,7 +28,12 @@ export type EstimateOperatorFeeParameters<
|
|
|
28
28
|
> = Omit<TransactionRequestEIP1559, 'from'> &
|
|
29
29
|
GetAccountParameter<TAccount> &
|
|
30
30
|
GetChainParameter<TChain, TChainOverride> & {
|
|
31
|
-
/**
|
|
31
|
+
/** Gas price oracle address. */
|
|
32
|
+
gasPriceOracleAddress?: Address | undefined
|
|
33
|
+
/**
|
|
34
|
+
* L1 block attributes contract address.
|
|
35
|
+
* @deprecated Use `gasPriceOracleAddress` instead.
|
|
36
|
+
*/
|
|
32
37
|
l1BlockAddress?: Address | undefined
|
|
33
38
|
}
|
|
34
39
|
|
|
@@ -46,7 +51,6 @@ export type EstimateOperatorFeeErrorType =
|
|
|
46
51
|
*
|
|
47
52
|
* Operator fees are part of the Isthmus upgrade and allow OP Stack operators
|
|
48
53
|
* to recover costs related to Alt-DA, ZK proving, or custom gas tokens.
|
|
49
|
-
* Returns 0 for pre-Isthmus chains or when operator fee functions don't exist.
|
|
50
54
|
*
|
|
51
55
|
* @param client - Client to use
|
|
52
56
|
* @param parameters - {@link EstimateOperatorFeeParameters}
|
|
@@ -75,45 +79,55 @@ export async function estimateOperatorFee<
|
|
|
75
79
|
client: Client<Transport, TChain, TAccount>,
|
|
76
80
|
args: EstimateOperatorFeeParameters<TChain, TAccount, TChainOverride>,
|
|
77
81
|
): Promise<EstimateOperatorFeeReturnType> {
|
|
78
|
-
const {
|
|
82
|
+
const {
|
|
83
|
+
chain = client.chain,
|
|
84
|
+
gasPriceOracleAddress: gasPriceOracleAddress_,
|
|
85
|
+
l1BlockAddress,
|
|
86
|
+
} = args
|
|
79
87
|
|
|
80
|
-
const
|
|
81
|
-
if (
|
|
82
|
-
if (chain
|
|
88
|
+
const gasPriceOracleAddress = (() => {
|
|
89
|
+
if (gasPriceOracleAddress_) return gasPriceOracleAddress_
|
|
90
|
+
if (chain)
|
|
83
91
|
return getChainContractAddress({
|
|
84
92
|
chain,
|
|
85
|
-
contract: '
|
|
93
|
+
contract: 'gasPriceOracle',
|
|
86
94
|
})
|
|
87
|
-
return contracts.
|
|
88
|
-
})()
|
|
95
|
+
return contracts.gasPriceOracle.address
|
|
96
|
+
})() as Address
|
|
89
97
|
|
|
90
|
-
|
|
91
|
-
// it means this is a pre-Isthmus chain and operator fees don't apply
|
|
92
|
-
try {
|
|
93
|
-
// Get operator fee parameters first to fail fast if not supported
|
|
94
|
-
const [operatorFeeScalar, operatorFeeConstant] = await Promise.all([
|
|
95
|
-
readContract(client, {
|
|
96
|
-
abi: l1BlockAbi,
|
|
97
|
-
address: l1BlockAddress,
|
|
98
|
-
functionName: 'operatorFeeScalar',
|
|
99
|
-
}),
|
|
100
|
-
readContract(client, {
|
|
101
|
-
abi: l1BlockAbi,
|
|
102
|
-
address: l1BlockAddress,
|
|
103
|
-
functionName: 'operatorFeeConstant',
|
|
104
|
-
}),
|
|
105
|
-
])
|
|
98
|
+
const gasUsed = await estimateGas(client, args as EstimateGasParameters)
|
|
106
99
|
|
|
107
|
-
|
|
108
|
-
|
|
100
|
+
if (l1BlockAddress) {
|
|
101
|
+
// `isJovian` is unavailable on Isthmus Gas Price Oracle implementations.
|
|
102
|
+
const [operatorFeeScalar, operatorFeeConstant, isJovian] =
|
|
103
|
+
await Promise.all([
|
|
104
|
+
readContract(client, {
|
|
105
|
+
abi: l1BlockAbi,
|
|
106
|
+
address: l1BlockAddress,
|
|
107
|
+
functionName: 'operatorFeeScalar',
|
|
108
|
+
}),
|
|
109
|
+
readContract(client, {
|
|
110
|
+
abi: l1BlockAbi,
|
|
111
|
+
address: l1BlockAddress,
|
|
112
|
+
functionName: 'operatorFeeConstant',
|
|
113
|
+
}),
|
|
114
|
+
readContract(client, {
|
|
115
|
+
abi: gasPriceOracleAbi,
|
|
116
|
+
address: gasPriceOracleAddress,
|
|
117
|
+
functionName: 'isJovian',
|
|
118
|
+
}).catch(() => false),
|
|
119
|
+
])
|
|
109
120
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
return
|
|
114
|
-
} catch {
|
|
115
|
-
// If any call fails, this is likely a pre-Isthmus chain or the contract
|
|
116
|
-
// doesn't support these functions. Return 0 for operator fee.
|
|
117
|
-
return 0n
|
|
121
|
+
const scalar = BigInt(operatorFeeScalar)
|
|
122
|
+
const constant = BigInt(operatorFeeConstant)
|
|
123
|
+
if (isJovian) return gasUsed * scalar * 100n + constant
|
|
124
|
+
return (gasUsed * scalar) / 1_000_000n + constant
|
|
118
125
|
}
|
|
126
|
+
|
|
127
|
+
return readContract(client, {
|
|
128
|
+
abi: gasPriceOracleAbi,
|
|
129
|
+
address: gasPriceOracleAddress,
|
|
130
|
+
functionName: 'getOperatorFee',
|
|
131
|
+
args: [gasUsed],
|
|
132
|
+
})
|
|
119
133
|
}
|