@@ -73,6 +73,9 @@ public class WriteTransaction: ReadTransaction {
7373 optionsForGasEstimation. value = mergedOptions. value
7474 optionsForGasEstimation. gasLimit = mergedOptions. gasLimit
7575 optionsForGasEstimation. callOnBlock = mergedOptions. callOnBlock
76+ optionsForGasEstimation. type = mergedOptions. type
77+ optionsForGasEstimation. accessList = mergedOptions. accessList
78+
7679
7780 // assemble promise for gasLimit
7881 var gasEstimatePromise : Promise < BigUInt > ? = nil
@@ -102,20 +105,75 @@ public class WriteTransaction: ReadTransaction {
102105 getNoncePromise = Promise< BigUInt> . value( nonce)
103106 }
104107
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+ }
116172 }
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
119177
120178 promisesToFulfill. removeAll ( )
121179 guard case . fulfilled( let nonce) = results [ 0 ] else {
@@ -124,17 +182,25 @@ public class WriteTransaction: ReadTransaction {
124182 guard case . fulfilled( let gasEstimate) = results [ 1 ] else {
125183 throw Web3Error . processingError ( desc: " Failed to fetch gas estimate " )
126184 }
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)
133185
134186 var finalOptions = TransactionOptions ( )
187+ finalOptions. type = mergedOptions. type
135188 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+ }
138204
139205 assembledTransaction. applyOptions ( finalOptions)
140206
0 commit comments