1
1
import {
2
+ Account as StellarAccount ,
2
3
Asset ,
3
4
Keypair ,
4
5
Memo ,
@@ -13,7 +14,14 @@ import {
13
14
import { Account } from "~App/contexts/accounts"
14
15
import { WrongPasswordError , CustomError } from "./errors"
15
16
import { applyTimeout } from "./promise"
16
- import { getAllSources , isNotFoundError , isSignedByAnyOf , selectSmartTransactionFee , SmartFeePreset } from "./stellar"
17
+ import { getAllSources , isNotFoundError , isSignedByAnyOf } from "./stellar"
18
+ import { workers } from "~Workers/worker-controller"
19
+
20
+ interface SmartFeePreset {
21
+ capacityTrigger : number
22
+ maxFee : number
23
+ percentile : number
24
+ }
17
25
18
26
// See <https://github.com/stellar/go/issues/926>
19
27
const highFeePreset : SmartFeePreset = {
@@ -72,9 +80,20 @@ async function accountExists(horizon: Server, publicKey: string) {
72
80
}
73
81
}
74
82
75
- async function selectTransactionFeeWithFallback ( horizon : Server , fallbackFee : number ) {
83
+ async function selectTransactionFeeWithFallback ( horizonURL : string , preset : SmartFeePreset , fallbackFee : number ) {
76
84
try {
77
- return await selectSmartTransactionFee ( horizon , highFeePreset )
85
+ const { netWorker } = await workers
86
+ const feeStats = await netWorker . fetchFeeStats ( horizonURL )
87
+
88
+ const capacityUsage = Number . parseFloat ( feeStats . ledger_capacity_usage )
89
+ const percentileFees = feeStats . fee_charged
90
+
91
+ const smartFee =
92
+ capacityUsage > preset . capacityTrigger
93
+ ? Number . parseInt ( ( percentileFees as any ) [ `p${ preset . percentile } ` ] || feeStats . fee_charged . mode , 10 )
94
+ : Number . parseInt ( feeStats . fee_charged . min , 10 )
95
+
96
+ return Math . min ( smartFee , preset . maxFee )
78
97
} catch ( error ) {
79
98
// Don't show error notification, since our horizon's endpoint is non-functional anyway
80
99
// tslint:disable-next-line no-console
@@ -98,17 +117,27 @@ interface TxBlueprint {
98
117
99
118
export async function createTransaction ( operations : Array < xdr . Operation < any > > , options : TxBlueprint ) {
100
119
const { horizon, walletAccount } = options
120
+ const { netWorker } = await workers
121
+
101
122
const fallbackFee = 10000
123
+ const horizonURL = horizon . serverURL . toString ( )
102
124
const timeout = selectTransactionTimeout ( options . accountData )
103
125
104
- const [ account , smartTxFee , timebounds ] = await Promise . all ( [
105
- applyTimeout ( horizon . loadAccount ( walletAccount . publicKey ) , 10000 , ( ) =>
126
+ const [ accountMetadata , smartTxFee , timebounds ] = await Promise . all ( [
127
+ applyTimeout ( netWorker . fetchAccountData ( horizonURL , walletAccount . publicKey ) , 10000 , ( ) =>
106
128
fail ( `Fetching source account data timed out` )
107
129
) ,
108
- applyTimeout ( selectTransactionFeeWithFallback ( horizon , fallbackFee ) , 5000 , ( ) => fallbackFee ) ,
109
- applyTimeout ( horizon . fetchTimebounds ( timeout ) , 10000 , ( ) => fail ( `Syncing time bounds with horizon timed out` ) )
110
- ] )
130
+ applyTimeout ( selectTransactionFeeWithFallback ( horizonURL , highFeePreset , fallbackFee ) , 5000 , ( ) => fallbackFee ) ,
131
+ applyTimeout ( netWorker . fetchTimebounds ( horizonURL , timeout ) , 10000 , ( ) =>
132
+ fail ( `Syncing time bounds with horizon timed out` )
133
+ )
134
+ ] as const )
111
135
136
+ if ( ! accountMetadata ) {
137
+ throw Error ( `Failed to query account from horizon server: ${ walletAccount . publicKey } ` )
138
+ }
139
+
140
+ const account = new StellarAccount ( accountMetadata . id , accountMetadata . sequence )
112
141
const networkPassphrase = walletAccount . testnet ? Networks . TESTNET : Networks . PUBLIC
113
142
const txFee = Math . max ( smartTxFee , options . minTransactionFee || 0 )
114
143
@@ -163,13 +192,23 @@ export async function signTransaction(transaction: Transaction, walletAccount: A
163
192
}
164
193
165
194
export async function requiresRemoteSignatures ( horizon : Server , transaction : Transaction , walletPublicKey : string ) {
195
+ const { netWorker } = await workers
196
+ const horizonURL = horizon . serverURL . toString ( )
166
197
const sources = getAllSources ( transaction )
167
198
168
199
if ( sources . length > 1 ) {
169
200
return true
170
201
}
171
202
172
- const accounts = await Promise . all ( sources . map ( sourcePublicKey => horizon . loadAccount ( sourcePublicKey ) ) )
203
+ const accounts = await Promise . all (
204
+ sources . map ( async sourcePublicKey => {
205
+ const account = await netWorker . fetchAccountData ( horizonURL , sourcePublicKey )
206
+ if ( ! account ) {
207
+ throw Error ( `Could not fetch account metadata from horizon server: ${ sourcePublicKey } ` )
208
+ }
209
+ return account
210
+ } )
211
+ )
173
212
174
213
return accounts . some ( account => {
175
214
const thisWalletSigner = account . signers . find ( signer => signer . key === walletPublicKey )
0 commit comments