@@ -10,163 +10,121 @@ import BigInt
10
10
public class WriteTransaction : ReadTransaction {
11
11
12
12
public func assemblePromise( transactionOptions: TransactionOptions ? = nil ) async throws -> EthereumTransaction {
13
- var assembledTransaction : EthereumTransaction = self . transaction
14
- let queue = self . web3. requestDispatcher. queue
15
- let returnPromise = Promise< EthereumTransaction> { seal in
16
- if self . method != " fallback " {
17
- let m = self . contract. methods [ self . method]
18
- if m == nil {
19
- seal. reject ( Web3Error . inputError ( desc: " Contract's ABI does not have such method " ) )
20
- return
21
- }
22
- switch m! {
23
- case . function( let function) :
24
- if function. constant {
25
- seal. reject ( Web3Error . inputError ( desc: " Trying to transact to the constant function " ) )
26
- return
27
- }
28
- case . constructor( _) :
29
- break
30
- default :
31
- seal. reject ( Web3Error . inputError ( desc: " Contract's ABI does not have such method " ) )
32
- return
33
- }
34
- }
13
+ var assembledTransaction : EthereumTransaction = self . transaction
35
14
36
- var mergedOptions = self . transactionOptions. merge ( transactionOptions)
37
- if mergedOptions. value != nil {
38
- assembledTransaction. value = mergedOptions. value!
39
- }
40
- var forAssemblyPipeline : ( EthereumTransaction , EthereumContract , TransactionOptions ) = ( assembledTransaction, self . contract, mergedOptions)
41
-
42
- for hook in self . web3. preAssemblyHooks {
43
- let prom : Promise < Bool > = Promise< Bool> { seal in
44
- hook. queue. async {
45
- let hookResult = hook. function ( forAssemblyPipeline)
46
- if hookResult. 3 {
47
- forAssemblyPipeline = ( hookResult. 0 , hookResult. 1 , hookResult. 2 )
48
- }
49
- seal. fulfill ( hookResult. 3 )
50
- }
51
- }
52
- let shouldContinue = try prom. wait ( )
53
- if !shouldContinue {
54
- seal. reject ( Web3Error . processingError ( desc: " Transaction is canceled by middleware " ) )
55
- return
56
- }
15
+ if self . method != " fallback " {
16
+ let m = self . contract. methods [ self . method]
17
+ if m == nil {
18
+ throw Web3Error . inputError ( desc: " Contract's ABI does not have such method " )
19
+ }
20
+ switch m! {
21
+ case . function( let function) :
22
+ if function. constant {
23
+ throw Web3Error . inputError ( desc: " Trying to transact to the constant function " )
57
24
}
25
+ case . constructor( _) :
26
+ break
27
+ default :
28
+ throw Web3Error . inputError ( desc: " Contract's ABI does not have such method " )
29
+ }
30
+ }
58
31
59
- assembledTransaction = forAssemblyPipeline. 0
60
- mergedOptions = forAssemblyPipeline. 2
32
+ var mergedOptions = self . transactionOptions. merge ( transactionOptions)
33
+ if mergedOptions. value != nil {
34
+ assembledTransaction. value = mergedOptions. value!
35
+ }
36
+ var forAssemblyPipeline : ( EthereumTransaction , EthereumContract , TransactionOptions ) = ( assembledTransaction, self . contract, mergedOptions)
61
37
62
- guard let from = mergedOptions. from else {
63
- seal. reject ( Web3Error . inputError ( desc: " No 'from' field provided " ) )
64
- return
65
- }
38
+ for hook in self . web3. preAssemblyHooks {
39
+ let hookResult = hook. function ( forAssemblyPipeline)
40
+ if hookResult. 3 {
41
+ forAssemblyPipeline = ( hookResult. 0 , hookResult. 1 , hookResult. 2 )
42
+ }
66
43
67
- // assemble promise for gas estimation
68
- var optionsForGasEstimation = TransactionOptions ( )
69
- optionsForGasEstimation. from = mergedOptions. from
70
- optionsForGasEstimation. to = mergedOptions. to
71
- optionsForGasEstimation. value = mergedOptions. value
72
- optionsForGasEstimation. gasLimit = mergedOptions. gasLimit
73
- optionsForGasEstimation. callOnBlock = mergedOptions. callOnBlock
74
-
75
- // assemble promise for gasLimit
76
- var gasEstimatePromise : Promise < BigUInt > ? = nil
77
- guard let gasLimitPolicy = mergedOptions. gasLimit else {
78
- seal. reject ( Web3Error . inputError ( desc: " No gasLimit policy provided " ) )
79
- return
80
- }
81
- switch gasLimitPolicy {
82
- case . automatic, . withMargin, . limited:
83
- gasEstimatePromise = self . web3. eth. estimateGasPromise ( assembledTransaction, transactionOptions: optionsForGasEstimation)
84
- case . manual( let gasLimit) :
85
- gasEstimatePromise = Promise< BigUInt> . value( gasLimit)
86
- }
44
+ let shouldContinue = hookResult. 3
45
+ if !shouldContinue {
46
+ throw Web3Error . processingError ( desc: " Transaction is canceled by middleware " )
47
+ }
48
+ }
87
49
88
- // assemble promise for nonce
89
- var getNoncePromise : Promise < BigUInt > ?
90
- guard let noncePolicy = mergedOptions. nonce else {
91
- seal. reject ( Web3Error . inputError ( desc: " No nonce policy provided " ) )
92
- return
93
- }
94
- switch noncePolicy {
95
- case . latest:
96
- getNoncePromise = self . web3. eth. getTransactionCountPromise ( address: from, onBlock: " latest " )
97
- case . pending:
98
- getNoncePromise = self . web3. eth. getTransactionCountPromise ( address: from, onBlock: " pending " )
99
- case . manual( let nonce) :
100
- getNoncePromise = Promise< BigUInt> . value( nonce)
101
- }
50
+ assembledTransaction = forAssemblyPipeline. 0
51
+ mergedOptions = forAssemblyPipeline. 2
102
52
103
- // assemble promise for gasPrice
104
- var gasPricePromise : Promise < BigUInt > ? = nil
105
- guard let gasPricePolicy = mergedOptions. gasPrice else {
106
- seal. reject ( Web3Error . inputError ( desc: " No gasPrice policy provided " ) )
107
- return
108
- }
109
- switch gasPricePolicy {
110
- case . automatic, . withMargin:
111
- gasPricePromise = self . web3. eth. getGasPricePromise ( )
112
- case . manual( let gasPrice) :
113
- gasPricePromise = Promise< BigUInt> . value( gasPrice)
114
- }
115
- var promisesToFulfill : [ Promise < BigUInt > ] = [ getNoncePromise!, gasPricePromise!, gasEstimatePromise!]
116
- when ( resolved: getNoncePromise!, gasEstimatePromise!, gasPricePromise!) . map ( on: queue, { ( results: [ PromiseResult < BigUInt > ] ) throws -> EthereumTransaction in
117
-
118
- promisesToFulfill. removeAll ( )
119
- guard case . fulfilled( let nonce) = results [ 0 ] else {
120
- throw Web3Error . processingError ( desc: " Failed to fetch nonce " )
121
- }
122
- guard case . fulfilled( let gasEstimate) = results [ 1 ] else {
123
- throw Web3Error . processingError ( desc: " Failed to fetch gas estimate " )
124
- }
125
- guard case . fulfilled( let gasPrice) = results [ 2 ] else {
126
- throw Web3Error . processingError ( desc: " Failed to fetch gas price " )
127
- }
128
-
129
- let estimate = mergedOptions. resolveGasLimit ( gasEstimate)
130
- let finalGasPrice = mergedOptions. resolveGasPrice ( gasPrice)
131
-
132
- var finalOptions = TransactionOptions ( )
133
- finalOptions. nonce = . manual( nonce)
134
- finalOptions. gasLimit = . manual( estimate)
135
- finalOptions. gasPrice = . manual( finalGasPrice)
136
-
137
- assembledTransaction. applyOptions ( finalOptions)
138
-
139
- forAssemblyPipeline = ( assembledTransaction, self . contract, mergedOptions)
140
-
141
- for hook in self . web3. postAssemblyHooks {
142
- let prom : Promise < Bool > = Promise< Bool> { seal in
143
- hook. queue. async {
144
- let hookResult = hook. function ( forAssemblyPipeline)
145
- if hookResult. 3 {
146
- forAssemblyPipeline = ( hookResult. 0 , hookResult. 1 , hookResult. 2 )
147
- }
148
- seal. fulfill ( hookResult. 3 )
149
- }
150
- }
151
- let shouldContinue = try prom. wait ( )
152
- if !shouldContinue {
153
- throw Web3Error . processingError ( desc: " Transaction is canceled by middleware " )
154
- }
155
- }
156
-
157
- assembledTransaction = forAssemblyPipeline. 0
158
- mergedOptions = forAssemblyPipeline. 2
159
-
160
- return assembledTransaction
161
- } ) . done ( on: queue) { tx in
162
- seal. fulfill ( tx)
163
- } . catch ( on: queue) { err in
164
- seal. reject ( err)
165
- }
53
+ guard let from = mergedOptions. from else {
54
+ throw Web3Error . inputError ( desc: " No 'from' field provided " )
55
+ }
56
+
57
+ // assemble promise for gas estimation
58
+ var optionsForGasEstimation = TransactionOptions ( )
59
+ optionsForGasEstimation. from = mergedOptions. from
60
+ optionsForGasEstimation. to = mergedOptions. to
61
+ optionsForGasEstimation. value = mergedOptions. value
62
+ optionsForGasEstimation. gasLimit = mergedOptions. gasLimit
63
+ optionsForGasEstimation. callOnBlock = mergedOptions. callOnBlock
64
+
65
+ // assemble promise for gasLimit
66
+
67
+ guard let gasLimitPolicy = mergedOptions. gasLimit else {
68
+ throw Web3Error . inputError ( desc: " No gasLimit policy provided " )
69
+ }
70
+
71
+ guard let gasPricePolicy = mergedOptions. gasPrice else {
72
+ throw Web3Error . inputError ( desc: " No gasPrice policy provided " )
73
+ }
74
+
75
+ guard let noncePolicy = mergedOptions. nonce else {
76
+ throw Web3Error . inputError ( desc: " No nonce policy provided " )
77
+ }
78
+
79
+
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
+
92
+
93
+ let results = try await [ getNoncePromise, gasPricePromise, gasEstimatePromise]
94
+
95
+ let nonce = results [ 0 ]
96
+ let gasEstimate = results [ 1 ]
97
+ let gasPrice = results [ 2 ]
98
+
99
+
100
+ let estimate = mergedOptions. resolveGasLimit ( gasEstimate)
101
+ let finalGasPrice = mergedOptions. resolveGasPrice ( gasPrice)
102
+
103
+ var finalOptions = TransactionOptions ( )
104
+ finalOptions. nonce = . manual( nonce)
105
+ finalOptions. gasLimit = . manual( estimate)
106
+ finalOptions. gasPrice = . manual( finalGasPrice)
107
+
108
+ assembledTransaction. applyOptions ( finalOptions)
109
+
110
+ forAssemblyPipeline = ( assembledTransaction, self . contract, mergedOptions)
111
+
112
+ for hook in self . web3. postAssemblyHooks {
113
+ let hookResult = hook. function ( forAssemblyPipeline)
114
+ if hookResult. 3 {
115
+ forAssemblyPipeline = ( hookResult. 0 , hookResult. 1 , hookResult. 2 )
116
+ }
117
+ let shouldContinue = hookResult. 3
118
+ if !shouldContinue {
119
+ throw Web3Error . processingError ( desc: " Transaction is canceled by middleware " )
166
120
}
167
- return returnPromise
168
121
}
169
122
123
+
124
+ return assembledTransaction
125
+
126
+ }
127
+
170
128
public func sendPromise( password: String = " web3swift " , transactionOptions: TransactionOptions ? = nil ) async throws -> TransactionSendingResult {
171
129
let transaction = try await self . assemblePromise ( transactionOptions: transactionOptions)
172
130
let mergedOptions = self . transactionOptions. merge ( transactionOptions)
0 commit comments