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