@@ -62,48 +62,107 @@ public class WriteTransaction: ReadTransaction {
62
62
optionsForGasEstimation. gasLimit = mergedOptions. gasLimit
63
63
optionsForGasEstimation. callOnBlock = mergedOptions. callOnBlock
64
64
65
- // assemble promise for gasLimit
66
-
65
+ // assemble gasLimit async call
66
+ let assembledTransactionPostHood = assembledTransaction
67
+ let optionsForGasEstimationPostHood = optionsForGasEstimation
67
68
guard let gasLimitPolicy = mergedOptions. gasLimit else {
68
69
throw Web3Error . inputError ( desc: " No gasLimit policy provided " )
69
70
}
71
+ async let gasEstimateAsync = gasEstimate ( for: gasLimitPolicy, assembledTransaction: assembledTransactionPostHood, optionsForGasEstimation: optionsForGasEstimationPostHood)
70
72
71
- guard let gasPricePolicy = mergedOptions. gasPrice else {
72
- throw Web3Error . inputError ( desc: " No gasPrice policy provided " )
73
- }
74
-
73
+ // assemble nonce async call
75
74
guard let noncePolicy = mergedOptions. nonce else {
76
75
throw Web3Error . inputError ( desc: " No nonce policy provided " )
77
76
}
77
+ async let getNonceAsync = nonce ( for: noncePolicy, from: from)
78
+
79
+ // determine gas costing, taking transaction type into account
80
+ let oracle = Web3 . Oracle ( self . web3, percentiles: [ 75 ] )
81
+ let finalGasPrice : BigUInt ? // legacy gas model
82
+ let finalGasFee : BigUInt ? // EIP-1559 gas model
83
+ let finalTipFee : BigUInt ? // EIP-1559 gas model
84
+
85
+ if mergedOptions. type == nil || mergedOptions. type != . eip1559 { // legacy Gas
86
+ // set unused gas parameters to nil
87
+ finalGasFee = nil
88
+ finalTipFee = nil
89
+
90
+ // determine the (legacy) gas price
91
+ guard let gasPricePolicy = mergedOptions. gasPrice else {
92
+ throw Web3Error . inputError ( desc: " No gasPrice policy provided " )
93
+ }
94
+ switch gasPricePolicy {
95
+ case . automatic, . withMargin:
96
+ let percentiles = await oracle. gasPriceLegacyPercentiles ( )
97
+ guard !percentiles. isEmpty else {
98
+ throw Web3Error . processingError ( desc: " Failed to fetch gas price " )
99
+ }
100
+ finalGasPrice = percentiles [ 0 ]
101
+ case . manual( let gasPrice) :
102
+ finalGasPrice = gasPrice
103
+ }
104
+ } else { // else new gas fees (EIP-1559)
105
+ // set unused gas parametes to nil
106
+ finalGasPrice = nil
78
107
108
+ // determine the tip
109
+ guard let maxPriorityFeePerGasPolicy = mergedOptions. maxPriorityFeePerGas else {
110
+ throw Web3Error . inputError ( desc: " No maxPriorityFeePerGas policy provided " )
111
+ }
112
+ switch maxPriorityFeePerGasPolicy {
113
+ case . automatic:
114
+ let percentiles = await oracle. tipFeePercentiles ( )
115
+ guard !percentiles. isEmpty else {
116
+ throw Web3Error . processingError ( desc: " Failed to fetch maxPriorityFeePerGas data " )
117
+ }
118
+ finalTipFee = percentiles [ 0 ]
119
+ case . manual( let maxPriorityFeePerGas) :
120
+ finalTipFee = maxPriorityFeePerGas
121
+ }
79
122
80
- let assembledTransactionPostHood = assembledTransaction
81
- let optionsForGasEstimationPostHood = optionsForGasEstimation
82
-
83
- async let gasEstimatePromise = gasEstimate ( for: gasLimitPolicy, assembledTransaction: assembledTransactionPostHood, optionsForGasEstimation: optionsForGasEstimationPostHood)
84
-
85
- // assemble promise for nonce
86
- async let getNoncePromise = nonce ( for: noncePolicy, from: from)
87
-
88
-
89
- // assemble promise for gasPrice
90
- async let gasPricePromise = gasPrice ( for: gasPricePolicy)
91
-
123
+ // determine the baseFee, and calculate the maxFeePerGas
124
+ guard let maxFeePerGasPolicy = mergedOptions. maxFeePerGas else {
125
+ throw Web3Error . inputError ( desc: " No maxFeePerGas policy provided " )
126
+ }
127
+ switch maxFeePerGasPolicy {
128
+ case . automatic:
129
+ let percentiles = await oracle. baseFeePercentiles ( )
130
+ guard !percentiles. isEmpty else {
131
+ throw Web3Error . processingError ( desc: " Failed to fetch baseFee data " )
132
+ }
133
+ guard let tipFee = finalTipFee else {
134
+ throw Web3Error . processingError ( desc: " Missing tip value " )
135
+ }
136
+ finalGasFee = percentiles [ 0 ] + tipFee
137
+ case . manual( let maxFeePerGas) :
138
+ finalGasFee = maxFeePerGas
139
+ }
140
+ }
92
141
93
- let results = try await [ getNoncePromise, gasPricePromise, gasEstimatePromise]
142
+ // wait for async calls to complete
143
+ let results = try await [ getNonceAsync, gasEstimateAsync]
94
144
95
145
let nonce = results [ 0 ]
96
146
let gasEstimate = results [ 1 ]
97
- let gasPrice = results [ 2 ]
98
-
99
-
100
- let estimate = mergedOptions. resolveGasLimit ( gasEstimate)
101
- let finalGasPrice = mergedOptions. resolveGasPrice ( gasPrice)
102
147
103
148
var finalOptions = TransactionOptions ( )
149
+ finalOptions. type = mergedOptions. type
104
150
finalOptions. nonce = . manual( nonce)
105
- finalOptions. gasLimit = . manual( estimate)
106
- finalOptions. gasPrice = . manual( finalGasPrice)
151
+ finalOptions. gasLimit = . manual( mergedOptions. resolveGasLimit ( gasEstimate) )
152
+ finalOptions. accessList = mergedOptions. accessList
153
+
154
+ // set the finalized gas parameters
155
+ if let gasPrice = finalGasPrice {
156
+ finalOptions. gasPrice = . manual( mergedOptions. resolveGasPrice ( gasPrice) )
157
+ }
158
+
159
+ if let tipFee = finalTipFee {
160
+ finalOptions. maxPriorityFeePerGas = . manual( mergedOptions. resolveMaxPriorityFeePerGas ( tipFee) )
161
+ }
162
+
163
+ if let gasFee = finalGasFee {
164
+ finalOptions. maxFeePerGas = . manual( mergedOptions. resolveMaxFeePerGas ( gasFee) )
165
+ }
107
166
108
167
assembledTransaction. applyOptions ( finalOptions)
109
168
@@ -120,9 +179,7 @@ public class WriteTransaction: ReadTransaction {
120
179
}
121
180
}
122
181
123
-
124
182
return assembledTransaction
125
-
126
183
}
127
184
128
185
public func send( password: String = " web3swift " , transactionOptions: TransactionOptions ? = nil ) async throws -> TransactionSendingResult {
@@ -138,8 +195,9 @@ public class WriteTransaction: ReadTransaction {
138
195
return try await self . assembleTransaction ( transactionOptions: transactionOptions)
139
196
}
140
197
141
- func gasEstimate( for policy: TransactionOptions . GasLimitPolicy
142
- , assembledTransaction: EthereumTransaction , optionsForGasEstimation: TransactionOptions ) async throws -> BigUInt {
198
+ func gasEstimate( for policy: TransactionOptions . GasLimitPolicy ,
199
+ assembledTransaction: EthereumTransaction ,
200
+ optionsForGasEstimation: TransactionOptions ) async throws -> BigUInt {
143
201
switch policy {
144
202
case . automatic, . withMargin, . limited:
145
203
return try await self . web3. eth. estimateGas ( for: assembledTransaction, transactionOptions: optionsForGasEstimation)
@@ -148,7 +206,7 @@ public class WriteTransaction: ReadTransaction {
148
206
}
149
207
}
150
208
151
- func nonce( for policy: TransactionOptions . NoncePolicy , from: EthereumAddress ) async throws -> BigUInt {
209
+ func nonce( for policy: TransactionOptions . NoncePolicy , from: EthereumAddress ) async throws -> BigUInt {
152
210
switch policy {
153
211
case . latest:
154
212
return try await self . web3. eth. getTransactionCount ( address: from, onBlock: " latest " )
@@ -158,13 +216,4 @@ public class WriteTransaction: ReadTransaction {
158
216
return nonce
159
217
}
160
218
}
161
-
162
- func gasPrice( for policy: TransactionOptions . GasPricePolicy ) async throws -> BigUInt {
163
- switch policy {
164
- case . automatic, . withMargin:
165
- return try await self . web3. eth. gasPrice ( )
166
- case . manual( let gasPrice) :
167
- return gasPrice
168
- }
169
- }
170
219
}
0 commit comments