viem 2.55.15 → 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.
Files changed (79) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/_cjs/actions/public/fillTransaction.js +45 -35
  3. package/_cjs/actions/public/fillTransaction.js.map +1 -1
  4. package/_cjs/actions/public/simulateCalls.js +213 -142
  5. package/_cjs/actions/public/simulateCalls.js.map +1 -1
  6. package/_cjs/actions/wallet/prepareTransactionRequest.js +4 -0
  7. package/_cjs/actions/wallet/prepareTransactionRequest.js.map +1 -1
  8. package/_cjs/chains/definitions/hausTestnet.js +27 -0
  9. package/_cjs/chains/definitions/hausTestnet.js.map +1 -0
  10. package/_cjs/chains/index.js +12 -10
  11. package/_cjs/chains/index.js.map +1 -1
  12. package/_cjs/errors/transaction.js +13 -1
  13. package/_cjs/errors/transaction.js.map +1 -1
  14. package/_cjs/errors/version.js +1 -1
  15. package/_cjs/index.js +5 -4
  16. package/_cjs/index.js.map +1 -1
  17. package/_cjs/op-stack/abis.js +14 -0
  18. package/_cjs/op-stack/abis.js.map +1 -1
  19. package/_cjs/op-stack/actions/estimateOperatorFee.js +26 -15
  20. package/_cjs/op-stack/actions/estimateOperatorFee.js.map +1 -1
  21. package/_cjs/utils/siwe/parseSiweMessage.js +16 -3
  22. package/_cjs/utils/siwe/parseSiweMessage.js.map +1 -1
  23. package/_cjs/utils/siwe/validateSiweMessage.js +13 -3
  24. package/_cjs/utils/siwe/validateSiweMessage.js.map +1 -1
  25. package/_esm/actions/public/fillTransaction.js +49 -36
  26. package/_esm/actions/public/fillTransaction.js.map +1 -1
  27. package/_esm/actions/public/simulateCalls.js +238 -150
  28. package/_esm/actions/public/simulateCalls.js.map +1 -1
  29. package/_esm/actions/wallet/prepareTransactionRequest.js +4 -0
  30. package/_esm/actions/wallet/prepareTransactionRequest.js.map +1 -1
  31. package/_esm/chains/definitions/hausTestnet.js +24 -0
  32. package/_esm/chains/definitions/hausTestnet.js.map +1 -0
  33. package/_esm/chains/index.js +1 -0
  34. package/_esm/chains/index.js.map +1 -1
  35. package/_esm/errors/transaction.js +11 -0
  36. package/_esm/errors/transaction.js.map +1 -1
  37. package/_esm/errors/version.js +1 -1
  38. package/_esm/index.js +1 -1
  39. package/_esm/index.js.map +1 -1
  40. package/_esm/op-stack/abis.js +14 -0
  41. package/_esm/op-stack/abis.js.map +1 -1
  42. package/_esm/op-stack/actions/estimateOperatorFee.js +28 -25
  43. package/_esm/op-stack/actions/estimateOperatorFee.js.map +1 -1
  44. package/_esm/utils/siwe/parseSiweMessage.js +18 -3
  45. package/_esm/utils/siwe/parseSiweMessage.js.map +1 -1
  46. package/_esm/utils/siwe/validateSiweMessage.js +16 -3
  47. package/_esm/utils/siwe/validateSiweMessage.js.map +1 -1
  48. package/_types/actions/public/fillTransaction.d.ts.map +1 -1
  49. package/_types/actions/public/simulateCalls.d.ts +5 -3
  50. package/_types/actions/public/simulateCalls.d.ts.map +1 -1
  51. package/_types/actions/wallet/prepareTransactionRequest.d.ts.map +1 -1
  52. package/_types/chains/definitions/hausTestnet.d.ts +52 -0
  53. package/_types/chains/definitions/hausTestnet.d.ts.map +1 -0
  54. package/_types/chains/index.d.ts +1 -0
  55. package/_types/chains/index.d.ts.map +1 -1
  56. package/_types/errors/transaction.d.ts +9 -0
  57. package/_types/errors/transaction.d.ts.map +1 -1
  58. package/_types/errors/version.d.ts +1 -1
  59. package/_types/index.d.ts +1 -1
  60. package/_types/index.d.ts.map +1 -1
  61. package/_types/op-stack/abis.d.ts +24 -0
  62. package/_types/op-stack/abis.d.ts.map +1 -1
  63. package/_types/op-stack/actions/estimateOperatorFee.d.ts +6 -2
  64. package/_types/op-stack/actions/estimateOperatorFee.d.ts.map +1 -1
  65. package/_types/utils/siwe/parseSiweMessage.d.ts.map +1 -1
  66. package/_types/utils/siwe/validateSiweMessage.d.ts.map +1 -1
  67. package/actions/public/fillTransaction.ts +53 -35
  68. package/actions/public/simulateCalls.ts +324 -181
  69. package/actions/wallet/prepareTransactionRequest.ts +6 -0
  70. package/chains/definitions/hausTestnet.ts +24 -0
  71. package/chains/index.ts +1 -0
  72. package/errors/transaction.ts +21 -0
  73. package/errors/version.ts +1 -1
  74. package/index.ts +2 -0
  75. package/op-stack/abis.ts +14 -0
  76. package/op-stack/actions/estimateOperatorFee.ts +50 -36
  77. package/package.json +1 -1
  78. package/utils/siwe/parseSiweMessage.ts +20 -3
  79. package/utils/siwe/validateSiweMessage.ts +13 -2
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
- /** L1 block attributes contract address. */
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 { chain = client.chain, l1BlockAddress: l1BlockAddress_ } = args
82
+ const {
83
+ chain = client.chain,
84
+ gasPriceOracleAddress: gasPriceOracleAddress_,
85
+ l1BlockAddress,
86
+ } = args
79
87
 
80
- const l1BlockAddress = (() => {
81
- if (l1BlockAddress_) return l1BlockAddress_
82
- if (chain?.contracts?.l1Block)
88
+ const gasPriceOracleAddress = (() => {
89
+ if (gasPriceOracleAddress_) return gasPriceOracleAddress_
90
+ if (chain)
83
91
  return getChainContractAddress({
84
92
  chain,
85
- contract: 'l1Block',
93
+ contract: 'gasPriceOracle',
86
94
  })
87
- return contracts.l1Block.address
88
- })()
95
+ return contracts.gasPriceOracle.address
96
+ })() as Address
89
97
 
90
- // Try to get operator fee parameters. If any of these calls fail,
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
- // Estimate gas for the actual transaction
108
- const gasUsed = await estimateGas(client, args as EstimateGasParameters)
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
- // Calculate operator fee: saturatingAdd(saturatingMul(gasUsed, scalar) / 1e6, constant)
111
- // Using saturating arithmetic to prevent overflow
112
- const scaledFee = (gasUsed * BigInt(operatorFeeScalar)) / 1_000_000n
113
- return scaledFee + BigInt(operatorFeeConstant)
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
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "viem",
3
3
  "description": "TypeScript Interface for Ethereum",
4
- "version": "2.55.15",
4
+ "version": "2.55.17",
5
5
  "main": "./_cjs/index.js",
6
6
  "module": "./_esm/index.js",
7
7
  "types": "./_types/index.d.ts",
@@ -3,6 +3,21 @@ import type { Address } from 'abitype'
3
3
  import type { ExactPartial, Prettify } from '../../types/utils.js'
4
4
  import type { SiweMessage } from './types.js'
5
5
 
6
+ const siweDateTimeRegex =
7
+ /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/
8
+
9
+ function isValidSiweDateTime(value: string): boolean {
10
+ if (!siweDateTimeRegex.test(value)) return false
11
+ return !Number.isNaN(new Date(value).getTime())
12
+ }
13
+
14
+ function parseSiweDateTime(value: string): Date {
15
+ // Reject non-RFC-3339 / non-EIP-4361 date-time strings before Date coercion
16
+ // (JS Date accepts many non-SIWE forms that would otherwise look "valid").
17
+ if (!isValidSiweDateTime(value)) return new Date(Number.NaN)
18
+ return new Date(value)
19
+ }
20
+
6
21
  /**
7
22
  * @description Parses EIP-4361 formatted message into message fields object.
8
23
  *
@@ -36,9 +51,11 @@ export function parseSiweMessage(
36
51
  ...prefix,
37
52
  ...suffix,
38
53
  ...(chainId ? { chainId: Number(chainId) } : {}),
39
- ...(expirationTime ? { expirationTime: new Date(expirationTime) } : {}),
40
- ...(issuedAt ? { issuedAt: new Date(issuedAt) } : {}),
41
- ...(notBefore ? { notBefore: new Date(notBefore) } : {}),
54
+ ...(expirationTime
55
+ ? { expirationTime: parseSiweDateTime(expirationTime) }
56
+ : {}),
57
+ ...(issuedAt ? { issuedAt: parseSiweDateTime(issuedAt) } : {}),
58
+ ...(notBefore ? { notBefore: parseSiweDateTime(notBefore) } : {}),
42
59
  ...(requestId ? { requestId } : {}),
43
60
  ...(resources ? { resources } : {}),
44
61
  ...(scheme ? { scheme } : {}),
@@ -57,8 +57,19 @@ export function validateSiweMessage(
57
57
  if (nonce && message.nonce !== nonce) return false
58
58
  if (scheme && message.scheme !== scheme) return false
59
59
 
60
- if (message.expirationTime && time >= message.expirationTime) return false
61
- if (message.notBefore && time < message.notBefore) return false
60
+ // Invalid `time` makes both lifetime comparisons false in JS; reject first.
61
+ if (Number.isNaN(time.getTime())) return false
62
+
63
+ // Invalid Date (e.g. non-RFC-3339 SIWE timestamp coerced at parse) is truthy;
64
+ // comparisons against it are always false and previously skipped checks.
65
+ if (message.expirationTime) {
66
+ if (Number.isNaN(message.expirationTime.getTime())) return false
67
+ if (time >= message.expirationTime) return false
68
+ }
69
+ if (message.notBefore) {
70
+ if (Number.isNaN(message.notBefore.getTime())) return false
71
+ if (time < message.notBefore) return false
72
+ }
62
73
 
63
74
  try {
64
75
  if (!message.address) return false