@@ -73,6 +73,9 @@ public class WriteTransaction: ReadTransaction {
73
73
optionsForGasEstimation. value = mergedOptions. value
74
74
optionsForGasEstimation. gasLimit = mergedOptions. gasLimit
75
75
optionsForGasEstimation. callOnBlock = mergedOptions. callOnBlock
76
+ optionsForGasEstimation. type = mergedOptions. type
77
+ optionsForGasEstimation. accessList = mergedOptions. accessList
78
+
76
79
77
80
// assemble promise for gasLimit
78
81
var gasEstimatePromise : Promise < BigUInt > ? = nil
@@ -102,20 +105,75 @@ public class WriteTransaction: ReadTransaction {
102
105
getNoncePromise = Promise< BigUInt> . value( nonce)
103
106
}
104
107
105
- // assemble promise for gasPrice
106
- var gasPricePromise : Promise < BigUInt > ? = nil
107
- guard let gasPricePolicy = mergedOptions. gasPrice else {
108
- seal. reject ( Web3Error . inputError ( desc: " No gasPrice policy provided " ) )
109
- return
110
- }
111
- switch gasPricePolicy {
112
- case . automatic, . withMargin:
113
- gasPricePromise = self . web3. eth. getGasPricePromise ( )
114
- case . manual( let gasPrice) :
115
- gasPricePromise = Promise< BigUInt> . value( gasPrice)
108
+ // determine gas costing, taking transaction type into account
109
+ let oracle = Web3 . Oracle ( self . web3, percentiles: [ 75 ] )
110
+ let finalGasPrice : BigUInt ? // legacy gas model
111
+ let finalGasFee : BigUInt ? // EIP-1559 gas model
112
+ let finalTipFee : BigUInt ? // EIP-1559 gas model
113
+
114
+ if mergedOptions. type == nil || mergedOptions. type != . eip1559 { // legacy Gas
115
+ // set unused gas parameters to nil
116
+ finalGasFee = nil
117
+ finalTipFee = nil
118
+
119
+ // determine the (legacy) gas price
120
+ guard let gasPricePolicy = mergedOptions. gasPrice else {
121
+ seal. reject ( Web3Error . inputError ( desc: " No gasPrice policy provided " ) )
122
+ return
123
+ }
124
+ switch gasPricePolicy {
125
+ case . automatic, . withMargin:
126
+ let percentiles = oracle. gasPriceLegacyPercentiles
127
+ guard !percentiles. isEmpty else {
128
+ throw Web3Error . processingError ( desc: " Failed to fetch gas price " )
129
+ }
130
+ finalGasPrice = percentiles [ 0 ]
131
+ case . manual( let gasPrice) :
132
+ finalGasPrice = gasPrice
133
+ }
134
+ } else { // else new gas fees (EIP-1559)
135
+ // set unused gas parametes to nil
136
+ finalGasPrice = nil
137
+
138
+ // determine the tip
139
+ guard let maxPriorityFeePerGasPolicy = mergedOptions. maxPriorityFeePerGas else {
140
+ seal. reject ( Web3Error . inputError ( desc: " No maxPriorityFeePerGas policy provided " ) )
141
+ return
142
+ }
143
+ switch maxPriorityFeePerGasPolicy {
144
+ case . automatic:
145
+ let percentiles = oracle. tipFeePercentiles
146
+ guard !percentiles. isEmpty else {
147
+ throw Web3Error . processingError ( desc: " Failed to fetch maxPriorityFeePerGas data " )
148
+ }
149
+ finalTipFee = percentiles [ 0 ]
150
+ case . manual( let maxPriorityFeePerGas) :
151
+ finalTipFee = maxPriorityFeePerGas
152
+ }
153
+
154
+ // determine the baseFee, and calculate the maxFeePerGas
155
+ guard let maxFeePerGasPolicy = mergedOptions. maxFeePerGas else {
156
+ seal. reject ( Web3Error . inputError ( desc: " No maxFeePerGas policy provided " ) )
157
+ return
158
+ }
159
+ switch maxFeePerGasPolicy {
160
+ case . automatic:
161
+ let percentiles = oracle. baseFeePercentiles
162
+ guard !percentiles. isEmpty else {
163
+ throw Web3Error . processingError ( desc: " Failed to fetch baseFee data " )
164
+ }
165
+ guard let tipFee = finalTipFee else {
166
+ throw Web3Error . processingError ( desc: " Missing tip value " )
167
+ }
168
+ finalGasFee = percentiles [ 0 ] + tipFee
169
+ case . manual( let maxFeePerGas) :
170
+ finalGasFee = maxFeePerGas
171
+ }
116
172
}
117
- var promisesToFulfill : [ Promise < BigUInt > ] = [ getNoncePromise!, gasPricePromise!, gasEstimatePromise!]
118
- when ( resolved: getNoncePromise!, gasEstimatePromise!, gasPricePromise!) . map ( on: queue, { ( results: [ PromiseResult < BigUInt > ] ) throws -> EthereumTransaction in
173
+
174
+ // wait for promises to resolve
175
+ var promisesToFulfill : [ Promise < BigUInt > ] = [ getNoncePromise!, gasEstimatePromise!]
176
+ when ( resolved: getNoncePromise!, gasEstimatePromise!) . map ( on: queue, { ( results: [ PromiseResult < BigUInt > ] ) throws -> EthereumTransaction in
119
177
120
178
promisesToFulfill. removeAll ( )
121
179
guard case . fulfilled( let nonce) = results [ 0 ] else {
@@ -124,17 +182,25 @@ public class WriteTransaction: ReadTransaction {
124
182
guard case . fulfilled( let gasEstimate) = results [ 1 ] else {
125
183
throw Web3Error . processingError ( desc: " Failed to fetch gas estimate " )
126
184
}
127
- guard case . fulfilled( let gasPrice) = results [ 2 ] else {
128
- throw Web3Error . processingError ( desc: " Failed to fetch gas price " )
129
- }
130
-
131
- let estimate = mergedOptions. resolveGasLimit ( gasEstimate)
132
- let finalGasPrice = mergedOptions. resolveGasPrice ( gasPrice)
133
185
134
186
var finalOptions = TransactionOptions ( )
187
+ finalOptions. type = mergedOptions. type
135
188
finalOptions. nonce = . manual( nonce)
136
- finalOptions. gasLimit = . manual( estimate)
137
- finalOptions. gasPrice = . manual( finalGasPrice)
189
+ finalOptions. gasLimit = . manual( mergedOptions. resolveGasLimit ( gasEstimate) )
190
+ finalOptions. accessList = mergedOptions. accessList
191
+
192
+ // set the finalized gas parameters
193
+ if let gasPrice = finalGasPrice {
194
+ finalOptions. gasPrice = . manual( mergedOptions. resolveGasPrice ( gasPrice) )
195
+ }
196
+
197
+ if let tipFee = finalTipFee {
198
+ finalOptions. maxPriorityFeePerGas = . manual( mergedOptions. resolveMaxPriorityFeePerGas ( tipFee) )
199
+ }
200
+
201
+ if let gasFee = finalGasFee {
202
+ finalOptions. maxFeePerGas = . manual( mergedOptions. resolveMaxFeePerGas ( gasFee) )
203
+ }
138
204
139
205
assembledTransaction. applyOptions ( finalOptions)
140
206
0 commit comments