edge-currency-accountbased 0.7.72
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +713 -0
- package/LICENSE +29 -0
- package/README.md +63 -0
- package/index.js +3 -0
- package/lib/binance/bnbEngine.js +591 -0
- package/lib/binance/bnbInfo.js +43 -0
- package/lib/binance/bnbPlugin.js +168 -0
- package/lib/binance/bnbSchema.js +83 -0
- package/lib/binance/bnbTypes.js +39 -0
- package/lib/common/engine.js +918 -0
- package/lib/common/plugin.js +152 -0
- package/lib/common/schema.js +108 -0
- package/lib/common/types.js +85 -0
- package/lib/common/utils.js +378 -0
- package/lib/eos/eosEngine.js +1216 -0
- package/lib/eos/eosInfo.js +98 -0
- package/lib/eos/eosPlugin.js +314 -0
- package/lib/eos/eosSchema.js +190 -0
- package/lib/eos/eosTypes.js +88 -0
- package/lib/eos/telosInfo.js +94 -0
- package/lib/eos/waxInfo.js +95 -0
- package/lib/ethereum/etcInfo.js +121 -0
- package/lib/ethereum/ethEngine.js +832 -0
- package/lib/ethereum/ethInfo.js +1300 -0
- package/lib/ethereum/ethMiningFees.js +157 -0
- package/lib/ethereum/ethNetwork.js +2195 -0
- package/lib/ethereum/ethPlugin.js +377 -0
- package/lib/ethereum/ethSchema.js +61 -0
- package/lib/ethereum/ethTypes.js +461 -0
- package/lib/ethereum/ftminfo.js +102 -0
- package/lib/ethereum/rskInfo.js +101 -0
- package/lib/fio/fioConst.js +38 -0
- package/lib/fio/fioEngine.js +1250 -0
- package/lib/fio/fioError.js +38 -0
- package/lib/fio/fioInfo.js +72 -0
- package/lib/fio/fioPlugin.js +486 -0
- package/lib/fio/fioSchema.js +56 -0
- package/lib/index.js +44 -0
- package/lib/pluginError.js +32 -0
- package/lib/react-native/edge-currency-accountbased.js +239635 -0
- package/lib/react-native/edge-currency-accountbased.js.map +1 -0
- package/lib/react-native-io.js +41 -0
- package/lib/stellar/stellarEngine.js +563 -0
- package/lib/stellar/stellarInfo.js +37 -0
- package/lib/stellar/stellarPlugin.js +215 -0
- package/lib/stellar/stellarSchema.js +54 -0
- package/lib/stellar/stellarTypes.js +66 -0
- package/lib/tezos/tezosEngine.js +497 -0
- package/lib/tezos/tezosInfo.js +60 -0
- package/lib/tezos/tezosPlugin.js +174 -0
- package/lib/tezos/tezosTypes.js +110 -0
- package/lib/xrp/xrpEngine.js +583 -0
- package/lib/xrp/xrpInfo.js +47 -0
- package/lib/xrp/xrpPlugin.js +229 -0
- package/lib/xrp/xrpSchema.js +74 -0
- package/lib/xrp/xrpTypes.js +38 -0
- package/package.json +139 -0
- package/postinstall.sh +7 -0
|
@@ -0,0 +1,1250 @@
|
|
|
1
|
+
function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }//
|
|
2
|
+
|
|
3
|
+
import { FIOSDK } from '@fioprotocol/fiosdk'
|
|
4
|
+
import { EndPoint } from '@fioprotocol/fiosdk/lib/entities/EndPoint'
|
|
5
|
+
import { Transactions } from '@fioprotocol/fiosdk/lib/transactions/Transactions'
|
|
6
|
+
import { Constants as FioConstants } from '@fioprotocol/fiosdk/lib/utils/constants'
|
|
7
|
+
import { bns } from 'biggystring'
|
|
8
|
+
import {
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
InsufficientFundsError
|
|
17
|
+
} from 'edge-core-js/types'
|
|
18
|
+
|
|
19
|
+
import { CurrencyEngine } from '../common/engine.js'
|
|
20
|
+
import {
|
|
21
|
+
asyncWaterfall,
|
|
22
|
+
cleanTxLogs,
|
|
23
|
+
getDenomInfo,
|
|
24
|
+
promiseAny,
|
|
25
|
+
promiseNy,
|
|
26
|
+
shuffleArray,
|
|
27
|
+
timeout
|
|
28
|
+
} from '../common/utils'
|
|
29
|
+
import {
|
|
30
|
+
ACTIONS_TO_END_POINT_KEYS,
|
|
31
|
+
BROADCAST_ACTIONS,
|
|
32
|
+
HISTORY_NODE_ACTIONS,
|
|
33
|
+
HISTORY_NODE_OFFSET
|
|
34
|
+
} from './fioConst.js'
|
|
35
|
+
import { fioApiErrorCodes, FioError } from './fioError'
|
|
36
|
+
import { FioPlugin } from './fioPlugin.js'
|
|
37
|
+
import {
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
asFioHistoryNodeAction,
|
|
41
|
+
asGetFioName,
|
|
42
|
+
asHistoryResponse
|
|
43
|
+
} from './fioSchema.js'
|
|
44
|
+
|
|
45
|
+
const ADDRESS_POLL_MILLISECONDS = 10000
|
|
46
|
+
const BLOCKCHAIN_POLL_MILLISECONDS = 15000
|
|
47
|
+
const TRANSACTION_POLL_MILLISECONDS = 10000
|
|
48
|
+
const FEE_ACTION_MAP = {
|
|
49
|
+
addPublicAddress: {
|
|
50
|
+
action: 'getFeeForAddPublicAddress',
|
|
51
|
+
propName: 'fioAddress'
|
|
52
|
+
},
|
|
53
|
+
addPublicAddresses: {
|
|
54
|
+
action: 'getFeeForAddPublicAddress',
|
|
55
|
+
propName: 'fioAddress'
|
|
56
|
+
},
|
|
57
|
+
rejectFundsRequest: {
|
|
58
|
+
action: 'getFeeForRejectFundsRequest',
|
|
59
|
+
propName: 'payerFioAddress'
|
|
60
|
+
},
|
|
61
|
+
requestFunds: {
|
|
62
|
+
action: 'getFeeForNewFundsRequest',
|
|
63
|
+
propName: 'payeeFioAddress'
|
|
64
|
+
},
|
|
65
|
+
recordObtData: {
|
|
66
|
+
action: 'getFeeForRecordObtData',
|
|
67
|
+
propName: 'payerFioAddress'
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
export class FioEngine extends CurrencyEngine {
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
localDataDirty() {
|
|
94
|
+
this.walletLocalDataDirty = true
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
constructor(
|
|
98
|
+
currencyPlugin,
|
|
99
|
+
walletInfo,
|
|
100
|
+
opts,
|
|
101
|
+
fetchCors,
|
|
102
|
+
tpid
|
|
103
|
+
) {
|
|
104
|
+
super(currencyPlugin, walletInfo, opts)
|
|
105
|
+
this.fetchCors = fetchCors
|
|
106
|
+
this.fioPlugin = currencyPlugin
|
|
107
|
+
this.tpid = tpid
|
|
108
|
+
this.recentFioFee = { publicAddress: '', fee: 0 }
|
|
109
|
+
|
|
110
|
+
this.fioSdkInit()
|
|
111
|
+
|
|
112
|
+
this.otherMethods = {
|
|
113
|
+
fioAction: async (actionName, params) => {
|
|
114
|
+
switch (actionName) {
|
|
115
|
+
case 'addPublicAddresses':
|
|
116
|
+
case 'addPublicAddress':
|
|
117
|
+
case 'requestFunds':
|
|
118
|
+
case 'rejectFundsRequest': {
|
|
119
|
+
const { fee } = await this.multicastServers(
|
|
120
|
+
FEE_ACTION_MAP[actionName].action,
|
|
121
|
+
{
|
|
122
|
+
[FEE_ACTION_MAP[actionName].propName]:
|
|
123
|
+
params[FEE_ACTION_MAP[actionName].propName]
|
|
124
|
+
}
|
|
125
|
+
)
|
|
126
|
+
params.maxFee = fee
|
|
127
|
+
break
|
|
128
|
+
}
|
|
129
|
+
case 'recordObtData': {
|
|
130
|
+
const { fee } = await this.multicastServers(
|
|
131
|
+
FEE_ACTION_MAP[actionName].action,
|
|
132
|
+
{
|
|
133
|
+
[FEE_ACTION_MAP[actionName].propName]:
|
|
134
|
+
params[FEE_ACTION_MAP[actionName].propName]
|
|
135
|
+
}
|
|
136
|
+
)
|
|
137
|
+
params.maxFee = fee
|
|
138
|
+
|
|
139
|
+
if (params.fioRequestId) {
|
|
140
|
+
this.walletLocalData.otherData.fioRequestsToApprove[
|
|
141
|
+
params.fioRequestId
|
|
142
|
+
] = params
|
|
143
|
+
this.localDataDirty()
|
|
144
|
+
const res = await this.multicastServers(actionName, params)
|
|
145
|
+
if (res && res.status === 'sent_to_blockchain') {
|
|
146
|
+
delete this.walletLocalData.otherData.fioRequestsToApprove[
|
|
147
|
+
params.fioRequestId
|
|
148
|
+
]
|
|
149
|
+
this.localDataDirty()
|
|
150
|
+
}
|
|
151
|
+
return res
|
|
152
|
+
}
|
|
153
|
+
break
|
|
154
|
+
}
|
|
155
|
+
case 'renewFioAddress': {
|
|
156
|
+
const { fee } = await this.multicastServers('getFee', {
|
|
157
|
+
endPoint: EndPoint[actionName]
|
|
158
|
+
})
|
|
159
|
+
params.maxFee = fee
|
|
160
|
+
const res = await this.multicastServers(actionName, params)
|
|
161
|
+
const renewedAddress =
|
|
162
|
+
this.walletLocalData.otherData.fioAddresses.find(
|
|
163
|
+
({ name }) => name === params.fioAddress
|
|
164
|
+
)
|
|
165
|
+
if (renewedAddress) {
|
|
166
|
+
renewedAddress.expiration = res.expiration
|
|
167
|
+
this.localDataDirty()
|
|
168
|
+
}
|
|
169
|
+
return res
|
|
170
|
+
}
|
|
171
|
+
case 'registerFioAddress': {
|
|
172
|
+
const { fee } = await this.multicastServers('getFee', {
|
|
173
|
+
endPoint: EndPoint[actionName]
|
|
174
|
+
})
|
|
175
|
+
params.maxFee = fee
|
|
176
|
+
const res = await this.multicastServers(actionName, params)
|
|
177
|
+
if (
|
|
178
|
+
params.ownerPublicKey &&
|
|
179
|
+
params.ownerPublicKey !== this.walletInfo.keys.publicKey
|
|
180
|
+
) {
|
|
181
|
+
return {
|
|
182
|
+
expiration: res.expiration,
|
|
183
|
+
feeCollected: res.fee_collected
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const addressAlreadyAdded =
|
|
187
|
+
this.walletLocalData.otherData.fioAddresses.find(
|
|
188
|
+
({ name }) => name === params.fioAddress
|
|
189
|
+
)
|
|
190
|
+
if (!addressAlreadyAdded) {
|
|
191
|
+
this.walletLocalData.otherData.fioAddresses.push({
|
|
192
|
+
name: params.fioAddress,
|
|
193
|
+
expiration: res.expiration
|
|
194
|
+
})
|
|
195
|
+
this.localDataDirty()
|
|
196
|
+
}
|
|
197
|
+
return res
|
|
198
|
+
}
|
|
199
|
+
case 'renewFioDomain': {
|
|
200
|
+
const { fee } = await this.multicastServers('getFee', {
|
|
201
|
+
endPoint: EndPoint[actionName]
|
|
202
|
+
})
|
|
203
|
+
params.maxFee = fee
|
|
204
|
+
const res = await this.multicastServers(actionName, params)
|
|
205
|
+
const renewedDomain =
|
|
206
|
+
this.walletLocalData.otherData.fioDomains.find(
|
|
207
|
+
({ name }) => name === params.fioDomain
|
|
208
|
+
)
|
|
209
|
+
if (renewedDomain) {
|
|
210
|
+
renewedDomain.expiration = res.expiration
|
|
211
|
+
this.localDataDirty()
|
|
212
|
+
}
|
|
213
|
+
return res
|
|
214
|
+
}
|
|
215
|
+
case 'registerFioDomain': {
|
|
216
|
+
const { fee } = await this.multicastServers('getFee', {
|
|
217
|
+
endPoint: EndPoint.registerFioDomain
|
|
218
|
+
})
|
|
219
|
+
params.max_fee = fee
|
|
220
|
+
const res = await this.multicastServers('pushTransaction', {
|
|
221
|
+
action: 'regdomain',
|
|
222
|
+
account: '',
|
|
223
|
+
data: {
|
|
224
|
+
...params,
|
|
225
|
+
tpid
|
|
226
|
+
}
|
|
227
|
+
})
|
|
228
|
+
return res
|
|
229
|
+
}
|
|
230
|
+
case 'transferFioDomain': {
|
|
231
|
+
const res = await this.multicastServers(actionName, params)
|
|
232
|
+
const transferredDomainIndex =
|
|
233
|
+
this.walletLocalData.otherData.fioDomains.findIndex(
|
|
234
|
+
({ name }) => name === params.fioDomain
|
|
235
|
+
)
|
|
236
|
+
if (transferredDomainIndex) {
|
|
237
|
+
this.walletLocalData.otherData.fioDomains.splice(
|
|
238
|
+
transferredDomainIndex,
|
|
239
|
+
1
|
|
240
|
+
)
|
|
241
|
+
this.localDataDirty()
|
|
242
|
+
}
|
|
243
|
+
return res
|
|
244
|
+
}
|
|
245
|
+
case 'transferFioAddress': {
|
|
246
|
+
const res = await this.multicastServers(actionName, params)
|
|
247
|
+
const transferredAddressIndex =
|
|
248
|
+
this.walletLocalData.otherData.fioAddresses.findIndex(
|
|
249
|
+
({ name }) => name === params.fioAddress
|
|
250
|
+
)
|
|
251
|
+
if (transferredAddressIndex) {
|
|
252
|
+
this.walletLocalData.otherData.fioAddresses.splice(
|
|
253
|
+
transferredAddressIndex,
|
|
254
|
+
1
|
|
255
|
+
)
|
|
256
|
+
this.localDataDirty()
|
|
257
|
+
}
|
|
258
|
+
return res
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return this.multicastServers(actionName, params)
|
|
263
|
+
},
|
|
264
|
+
getFee: async (
|
|
265
|
+
actionName,
|
|
266
|
+
fioAddress = ''
|
|
267
|
+
) => {
|
|
268
|
+
const { fee } = await this.multicastServers('getFee', {
|
|
269
|
+
endPoint: EndPoint[actionName],
|
|
270
|
+
fioAddress
|
|
271
|
+
})
|
|
272
|
+
return fee
|
|
273
|
+
},
|
|
274
|
+
getFioAddresses: async (
|
|
275
|
+
|
|
276
|
+
) => {
|
|
277
|
+
return this.walletLocalData.otherData.fioAddresses
|
|
278
|
+
},
|
|
279
|
+
getFioAddressNames: async () => {
|
|
280
|
+
return this.walletLocalData.otherData.fioAddresses.map(
|
|
281
|
+
fioAddress => fioAddress.name
|
|
282
|
+
)
|
|
283
|
+
},
|
|
284
|
+
getFioDomains: async (
|
|
285
|
+
|
|
286
|
+
) => {
|
|
287
|
+
return this.walletLocalData.otherData.fioDomains
|
|
288
|
+
},
|
|
289
|
+
getApproveNeededFioRequests: async (
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
) => {
|
|
304
|
+
return this.walletLocalData.otherData.fioRequestsToApprove
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Normalize date if not exists "Z" parameter
|
|
310
|
+
getUTCDate(dateString) {
|
|
311
|
+
const date = new Date(dateString)
|
|
312
|
+
|
|
313
|
+
return Date.UTC(
|
|
314
|
+
date.getFullYear(),
|
|
315
|
+
date.getMonth(),
|
|
316
|
+
date.getDate(),
|
|
317
|
+
date.getHours(),
|
|
318
|
+
date.getMinutes(),
|
|
319
|
+
date.getSeconds()
|
|
320
|
+
)
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
async loadEngine(
|
|
324
|
+
plugin,
|
|
325
|
+
walletInfo,
|
|
326
|
+
opts
|
|
327
|
+
) {
|
|
328
|
+
await super.loadEngine(plugin, walletInfo, opts)
|
|
329
|
+
if (typeof this.walletInfo.keys.ownerPublicKey !== 'string') {
|
|
330
|
+
if (walletInfo.keys.ownerPublicKey) {
|
|
331
|
+
this.walletInfo.keys.ownerPublicKey = walletInfo.keys.ownerPublicKey
|
|
332
|
+
} else {
|
|
333
|
+
const pubKeys = await plugin.derivePublicKey(this.walletInfo)
|
|
334
|
+
this.walletInfo.keys.ownerPublicKey = pubKeys.ownerPublicKey
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
await this.checkAbiAccounts()
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
fioSdkInit() {
|
|
342
|
+
const baseUrl = shuffleArray(
|
|
343
|
+
this.currencyInfo.defaultSettings.apiUrls.map(apiUrl => apiUrl)
|
|
344
|
+
)[0]
|
|
345
|
+
|
|
346
|
+
this.fioSdk = new FIOSDK(
|
|
347
|
+
this.walletInfo.keys.fioKey,
|
|
348
|
+
this.walletInfo.keys.publicKey,
|
|
349
|
+
baseUrl,
|
|
350
|
+
this.fetchCors,
|
|
351
|
+
undefined,
|
|
352
|
+
this.tpid
|
|
353
|
+
)
|
|
354
|
+
this.fioSdkPreparedTrx = new FIOSDK(
|
|
355
|
+
this.walletInfo.keys.fioKey,
|
|
356
|
+
this.walletInfo.keys.publicKey,
|
|
357
|
+
'',
|
|
358
|
+
this.fetchCors,
|
|
359
|
+
undefined,
|
|
360
|
+
this.tpid,
|
|
361
|
+
true
|
|
362
|
+
)
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
async checkAbiAccounts() {
|
|
366
|
+
if (Transactions.abiMap.size === FioConstants.rawAbiAccountName.length)
|
|
367
|
+
return
|
|
368
|
+
await asyncWaterfall(
|
|
369
|
+
shuffleArray(
|
|
370
|
+
this.currencyInfo.defaultSettings.apiUrls.map(
|
|
371
|
+
apiUrl => () => this.loadAbiAccounts(apiUrl)
|
|
372
|
+
)
|
|
373
|
+
)
|
|
374
|
+
)
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
async loadAbiAccounts(apiUrl) {
|
|
378
|
+
this.setFioSdkBaseUrl(apiUrl)
|
|
379
|
+
for (const accountName of FioConstants.rawAbiAccountName) {
|
|
380
|
+
if (Transactions.abiMap.get(accountName)) continue
|
|
381
|
+
const response = await this.fioSdk.getAbi(accountName)
|
|
382
|
+
Transactions.abiMap.set(response.account_name, response)
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
setFioSdkBaseUrl(apiUrl) {
|
|
387
|
+
Transactions.baseUrl = apiUrl
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// Poll on the blockheight
|
|
391
|
+
async checkBlockchainInnerLoop() {
|
|
392
|
+
try {
|
|
393
|
+
const info = await this.multicastServers('getChainInfo')
|
|
394
|
+
const blockHeight = info.head_block_num
|
|
395
|
+
if (this.walletLocalData.blockHeight !== blockHeight) {
|
|
396
|
+
this.checkDroppedTransactionsThrottled()
|
|
397
|
+
this.walletLocalData.blockHeight = blockHeight
|
|
398
|
+
this.localDataDirty()
|
|
399
|
+
this.currencyEngineCallbacks.onBlockHeightChanged(
|
|
400
|
+
this.walletLocalData.blockHeight
|
|
401
|
+
)
|
|
402
|
+
}
|
|
403
|
+
} catch (e) {
|
|
404
|
+
this.log.error(`checkBlockchainInnerLoop Error fetching height: ${e}`)
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
getBalance(options) {
|
|
409
|
+
return super.getBalance(options)
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
updateBalance(tk, balance) {
|
|
413
|
+
if (typeof this.walletLocalData.totalBalances[tk] === 'undefined') {
|
|
414
|
+
this.walletLocalData.totalBalances[tk] = '0'
|
|
415
|
+
}
|
|
416
|
+
if (!bns.eq(balance, this.walletLocalData.totalBalances[tk])) {
|
|
417
|
+
this.walletLocalData.totalBalances[tk] = balance
|
|
418
|
+
this.localDataDirty()
|
|
419
|
+
this.log.warn(tk + ': token Address balance: ' + balance)
|
|
420
|
+
this.currencyEngineCallbacks.onBalanceChanged(tk, balance)
|
|
421
|
+
}
|
|
422
|
+
this.tokenCheckBalanceStatus[tk] = 1
|
|
423
|
+
this.updateOnAddressesChecked()
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
processTransaction(action, actor) {
|
|
427
|
+
const {
|
|
428
|
+
act: { name: trxName, data }
|
|
429
|
+
} = action.action_trace
|
|
430
|
+
let nativeAmount
|
|
431
|
+
let actorSender
|
|
432
|
+
let networkFee = '0'
|
|
433
|
+
let otherParams
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
= {}
|
|
437
|
+
const currencyCode = this.currencyInfo.currencyCode
|
|
438
|
+
const ourReceiveAddresses = []
|
|
439
|
+
if (action.block_num <= this.walletLocalData.otherData.highestTxHeight) {
|
|
440
|
+
return action.block_num
|
|
441
|
+
}
|
|
442
|
+
if (trxName !== 'trnsfiopubky' && trxName !== 'transfer') {
|
|
443
|
+
return action.block_num
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// Transfer funds transaction
|
|
447
|
+
if (trxName === 'trnsfiopubky' && data.amount != null) {
|
|
448
|
+
nativeAmount = data.amount.toString()
|
|
449
|
+
actorSender = data.actor
|
|
450
|
+
if (data.payee_public_key === this.walletInfo.keys.publicKey) {
|
|
451
|
+
ourReceiveAddresses.push(this.walletInfo.keys.publicKey)
|
|
452
|
+
if (actorSender === actor) {
|
|
453
|
+
nativeAmount = '0'
|
|
454
|
+
}
|
|
455
|
+
} else {
|
|
456
|
+
nativeAmount = `-${nativeAmount}`
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
const index = this.findTransaction(
|
|
460
|
+
currencyCode,
|
|
461
|
+
action.action_trace.trx_id
|
|
462
|
+
)
|
|
463
|
+
// Check if fee transaction have already added
|
|
464
|
+
if (index > -1) {
|
|
465
|
+
const existingTrx = this.transactionList[currencyCode][index]
|
|
466
|
+
otherParams = { ...existingTrx.otherParams }
|
|
467
|
+
if (bns.gte(nativeAmount, '0')) {
|
|
468
|
+
return action.block_num
|
|
469
|
+
}
|
|
470
|
+
if (otherParams.isTransferProcessed) {
|
|
471
|
+
return action.block_num
|
|
472
|
+
}
|
|
473
|
+
if (otherParams.isFeeProcessed) {
|
|
474
|
+
nativeAmount = bns.sub(nativeAmount, existingTrx.networkFee)
|
|
475
|
+
networkFee = existingTrx.networkFee
|
|
476
|
+
} else {
|
|
477
|
+
this.log.error(
|
|
478
|
+
'processTransaction error - existing spend transaction should have isTransferProcessed or isFeeProcessed set'
|
|
479
|
+
)
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
otherParams.isTransferProcessed = true
|
|
483
|
+
|
|
484
|
+
const edgeTransaction = {
|
|
485
|
+
txid: action.action_trace.trx_id,
|
|
486
|
+
date: this.getUTCDate(action.block_time) / 1000,
|
|
487
|
+
currencyCode,
|
|
488
|
+
blockHeight: action.block_num > 0 ? action.block_num : 0,
|
|
489
|
+
nativeAmount,
|
|
490
|
+
networkFee,
|
|
491
|
+
parentNetworkFee: '0',
|
|
492
|
+
ourReceiveAddresses,
|
|
493
|
+
signedTx: '',
|
|
494
|
+
otherParams
|
|
495
|
+
}
|
|
496
|
+
this.addTransaction(currencyCode, edgeTransaction)
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// Fee transaction
|
|
500
|
+
if (trxName === 'transfer' && data.quantity != null) {
|
|
501
|
+
const [amount] = data.quantity.split(' ')
|
|
502
|
+
const exchangeAmount = amount.toString()
|
|
503
|
+
const denom = getDenomInfo(this.currencyInfo, currencyCode)
|
|
504
|
+
if (!denom) {
|
|
505
|
+
this.log.error(`Received unsupported currencyCode: ${currencyCode}`)
|
|
506
|
+
return 0
|
|
507
|
+
}
|
|
508
|
+
const fioAmount = bns.mul(exchangeAmount, denom.multiplier)
|
|
509
|
+
if (data.to === actor) {
|
|
510
|
+
nativeAmount = `${fioAmount}`
|
|
511
|
+
} else {
|
|
512
|
+
nativeAmount = `-${fioAmount}`
|
|
513
|
+
networkFee = fioAmount
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
const index = this.findTransaction(
|
|
517
|
+
currencyCode,
|
|
518
|
+
action.action_trace.trx_id
|
|
519
|
+
)
|
|
520
|
+
// Check if transfer transaction have already added
|
|
521
|
+
if (index > -1) {
|
|
522
|
+
const existingTrx = this.transactionList[currencyCode][index]
|
|
523
|
+
otherParams = { ...existingTrx.otherParams }
|
|
524
|
+
if (bns.gte(existingTrx.nativeAmount, '0')) {
|
|
525
|
+
return action.block_num
|
|
526
|
+
}
|
|
527
|
+
if (otherParams.isFeeProcessed) {
|
|
528
|
+
return action.block_num
|
|
529
|
+
}
|
|
530
|
+
if (otherParams.isTransferProcessed) {
|
|
531
|
+
nativeAmount = bns.sub(existingTrx.nativeAmount, networkFee)
|
|
532
|
+
} else {
|
|
533
|
+
this.log.error(
|
|
534
|
+
'processTransaction error - existing spend transaction should have isTransferProcessed or isFeeProcessed set'
|
|
535
|
+
)
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
otherParams.isFeeProcessed = true
|
|
540
|
+
const edgeTransaction = {
|
|
541
|
+
txid: action.action_trace.trx_id,
|
|
542
|
+
date: this.getUTCDate(action.block_time) / 1000,
|
|
543
|
+
currencyCode,
|
|
544
|
+
blockHeight: action.block_num > 0 ? action.block_num : 0,
|
|
545
|
+
nativeAmount,
|
|
546
|
+
networkFee,
|
|
547
|
+
signedTx: '',
|
|
548
|
+
ourReceiveAddresses: [],
|
|
549
|
+
otherParams
|
|
550
|
+
}
|
|
551
|
+
this.addTransaction(currencyCode, edgeTransaction)
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
return action.block_num
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
async checkTransactions(historyNodeIndex = 0) {
|
|
558
|
+
if (!this.currencyInfo.defaultSettings.historyNodeUrls[historyNodeIndex])
|
|
559
|
+
return false
|
|
560
|
+
let newHighestTxHeight = this.walletLocalData.otherData.highestTxHeight
|
|
561
|
+
let lastActionSeqNumber = 0
|
|
562
|
+
const actor = this.fioSdk.transactions.getActor(
|
|
563
|
+
this.walletInfo.keys.publicKey
|
|
564
|
+
)
|
|
565
|
+
try {
|
|
566
|
+
const lastActionObject = await this.requestHistory(
|
|
567
|
+
historyNodeIndex,
|
|
568
|
+
{
|
|
569
|
+
account_name: actor,
|
|
570
|
+
pos: -1,
|
|
571
|
+
offset: -1
|
|
572
|
+
},
|
|
573
|
+
HISTORY_NODE_ACTIONS.getActions
|
|
574
|
+
)
|
|
575
|
+
|
|
576
|
+
if (lastActionObject.error && lastActionObject.error.noNodeForIndex) {
|
|
577
|
+
// no more history nodes left
|
|
578
|
+
return false
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
asHistoryResponse(lastActionObject)
|
|
582
|
+
if (lastActionObject.actions.length) {
|
|
583
|
+
lastActionSeqNumber = lastActionObject.actions[0].account_action_seq
|
|
584
|
+
} else {
|
|
585
|
+
// if no transactions at all
|
|
586
|
+
return true
|
|
587
|
+
}
|
|
588
|
+
} catch (e) {
|
|
589
|
+
return this.checkTransactions(++historyNodeIndex)
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
let pos = lastActionSeqNumber
|
|
593
|
+
let finish = false
|
|
594
|
+
|
|
595
|
+
while (!finish) {
|
|
596
|
+
if (pos < 0) {
|
|
597
|
+
break
|
|
598
|
+
}
|
|
599
|
+
let actionsObject
|
|
600
|
+
try {
|
|
601
|
+
actionsObject = await this.requestHistory(
|
|
602
|
+
historyNodeIndex,
|
|
603
|
+
{
|
|
604
|
+
account_name: actor,
|
|
605
|
+
pos,
|
|
606
|
+
offset: -HISTORY_NODE_OFFSET + 1
|
|
607
|
+
},
|
|
608
|
+
HISTORY_NODE_ACTIONS.getActions
|
|
609
|
+
)
|
|
610
|
+
if (actionsObject.error && actionsObject.error.noNodeForIndex) {
|
|
611
|
+
return false
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
let actions = []
|
|
615
|
+
|
|
616
|
+
if (actionsObject.actions && actionsObject.actions.length > 0) {
|
|
617
|
+
actions = actionsObject.actions
|
|
618
|
+
} else {
|
|
619
|
+
break
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
for (let i = actions.length - 1; i > -1; i--) {
|
|
623
|
+
const action = actions[i]
|
|
624
|
+
asFioHistoryNodeAction(action)
|
|
625
|
+
const blockNum = this.processTransaction(action, actor)
|
|
626
|
+
|
|
627
|
+
if (blockNum > newHighestTxHeight) {
|
|
628
|
+
newHighestTxHeight = blockNum
|
|
629
|
+
} else if (
|
|
630
|
+
(blockNum === newHighestTxHeight &&
|
|
631
|
+
i === HISTORY_NODE_OFFSET - 1) ||
|
|
632
|
+
blockNum < this.walletLocalData.otherData.highestTxHeight
|
|
633
|
+
) {
|
|
634
|
+
finish = true
|
|
635
|
+
break
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
if (!actions.length || actions.length < HISTORY_NODE_OFFSET) {
|
|
640
|
+
break
|
|
641
|
+
}
|
|
642
|
+
pos -= HISTORY_NODE_OFFSET
|
|
643
|
+
} catch (e) {
|
|
644
|
+
return this.checkTransactions(++historyNodeIndex)
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
if (newHighestTxHeight > this.walletLocalData.otherData.highestTxHeight) {
|
|
648
|
+
this.walletLocalData.otherData.highestTxHeight = newHighestTxHeight
|
|
649
|
+
this.localDataDirty()
|
|
650
|
+
}
|
|
651
|
+
return true
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
async checkTransactionsInnerLoop() {
|
|
655
|
+
let transactions
|
|
656
|
+
try {
|
|
657
|
+
transactions = await this.checkTransactions()
|
|
658
|
+
} catch (e) {
|
|
659
|
+
this.log.error('checkTransactionsInnerLoop fetches failed with error: ')
|
|
660
|
+
this.log.error(e)
|
|
661
|
+
return false
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
if (transactions) {
|
|
665
|
+
this.tokenCheckTransactionsStatus.FIO = 1
|
|
666
|
+
this.updateOnAddressesChecked()
|
|
667
|
+
}
|
|
668
|
+
if (this.transactionsChangedArray.length > 0) {
|
|
669
|
+
this.currencyEngineCallbacks.onTransactionsChanged(
|
|
670
|
+
this.transactionsChangedArray
|
|
671
|
+
)
|
|
672
|
+
this.transactionsChangedArray = []
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
async requestHistory(
|
|
677
|
+
nodeIndex,
|
|
678
|
+
params
|
|
679
|
+
|
|
680
|
+
|
|
681
|
+
|
|
682
|
+
,
|
|
683
|
+
uri
|
|
684
|
+
) {
|
|
685
|
+
if (!this.currencyInfo.defaultSettings.historyNodeUrls[nodeIndex])
|
|
686
|
+
return { error: { noNodeForIndex: true } }
|
|
687
|
+
const apiUrl = this.currencyInfo.defaultSettings.historyNodeUrls[nodeIndex]
|
|
688
|
+
const result = await this.fetchCors(`${apiUrl}history/${uri || ''}`, {
|
|
689
|
+
method: 'POST',
|
|
690
|
+
headers: {
|
|
691
|
+
Accept: 'application/json',
|
|
692
|
+
'Content-Type': 'application/json'
|
|
693
|
+
},
|
|
694
|
+
body: JSON.stringify(params)
|
|
695
|
+
})
|
|
696
|
+
return result.json()
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
async fioApiRequest(
|
|
700
|
+
apiUrl,
|
|
701
|
+
actionName,
|
|
702
|
+
params,
|
|
703
|
+
returnPreparedTrx = false
|
|
704
|
+
) {
|
|
705
|
+
const fioSdk = returnPreparedTrx ? this.fioSdkPreparedTrx : this.fioSdk
|
|
706
|
+
this.setFioSdkBaseUrl(apiUrl)
|
|
707
|
+
|
|
708
|
+
let res
|
|
709
|
+
|
|
710
|
+
try {
|
|
711
|
+
switch (actionName) {
|
|
712
|
+
case 'getChainInfo':
|
|
713
|
+
res = await fioSdk.transactions.getChainInfo()
|
|
714
|
+
break
|
|
715
|
+
default:
|
|
716
|
+
res = await fioSdk.genericAction(actionName, params)
|
|
717
|
+
}
|
|
718
|
+
} catch (e) {
|
|
719
|
+
// handle FIO API error
|
|
720
|
+
if (e.errorCode && fioApiErrorCodes.indexOf(e.errorCode) > -1) {
|
|
721
|
+
if (
|
|
722
|
+
e.json &&
|
|
723
|
+
e.json.fields &&
|
|
724
|
+
e.json.fields[0] &&
|
|
725
|
+
e.json.fields[0].error
|
|
726
|
+
) {
|
|
727
|
+
e.message = e.json.fields[0].error
|
|
728
|
+
}
|
|
729
|
+
res = {
|
|
730
|
+
isError: true,
|
|
731
|
+
data: {
|
|
732
|
+
code: e.errorCode,
|
|
733
|
+
message: e.message,
|
|
734
|
+
json: e.json,
|
|
735
|
+
list: e.list
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
if (e.errorCode !== 404)
|
|
739
|
+
this.log(
|
|
740
|
+
`fioApiRequest error. actionName: ${actionName} - apiUrl: ${apiUrl} - message: ${JSON.stringify(
|
|
741
|
+
e.json
|
|
742
|
+
)}`
|
|
743
|
+
)
|
|
744
|
+
} else {
|
|
745
|
+
this.log(
|
|
746
|
+
`fioApiRequest error. actionName: ${actionName} - apiUrl: ${apiUrl} - message: ${e.message}`
|
|
747
|
+
)
|
|
748
|
+
throw e
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
return res
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
async executePreparedTrx(
|
|
756
|
+
apiUrl,
|
|
757
|
+
endpoint,
|
|
758
|
+
preparedTrx
|
|
759
|
+
) {
|
|
760
|
+
this.setFioSdkBaseUrl(apiUrl)
|
|
761
|
+
let res
|
|
762
|
+
|
|
763
|
+
this.log.warn(
|
|
764
|
+
`executePreparedTrx. preparedTrx: ${JSON.stringify(
|
|
765
|
+
preparedTrx
|
|
766
|
+
)} - apiUrl: ${apiUrl}`
|
|
767
|
+
)
|
|
768
|
+
try {
|
|
769
|
+
res = await this.fioSdk.executePreparedTrx(endpoint, preparedTrx)
|
|
770
|
+
this.log.warn(
|
|
771
|
+
`executePreparedTrx. res: ${JSON.stringify(
|
|
772
|
+
res
|
|
773
|
+
)} - apiUrl: ${apiUrl} - endpoint: ${endpoint}`
|
|
774
|
+
)
|
|
775
|
+
} catch (e) {
|
|
776
|
+
// handle FIO API error
|
|
777
|
+
if (e.errorCode && fioApiErrorCodes.indexOf(e.errorCode) > -1) {
|
|
778
|
+
this.log(
|
|
779
|
+
`executePreparedTrx error. requestParams: ${JSON.stringify(
|
|
780
|
+
preparedTrx
|
|
781
|
+
)} - apiUrl: ${apiUrl} - endpoint: ${endpoint} - message: ${JSON.stringify(
|
|
782
|
+
e.json
|
|
783
|
+
)}`
|
|
784
|
+
)
|
|
785
|
+
if (
|
|
786
|
+
e.json &&
|
|
787
|
+
e.json.fields &&
|
|
788
|
+
e.json.fields[0] &&
|
|
789
|
+
e.json.fields[0].error
|
|
790
|
+
) {
|
|
791
|
+
e.message = e.json.fields[0].error
|
|
792
|
+
}
|
|
793
|
+
throw e
|
|
794
|
+
} else {
|
|
795
|
+
this.log(
|
|
796
|
+
`executePreparedTrx error. requestParams: ${JSON.stringify(
|
|
797
|
+
preparedTrx
|
|
798
|
+
)} - apiUrl: ${apiUrl} - endpoint: ${endpoint} - message: ${
|
|
799
|
+
e.message
|
|
800
|
+
}`
|
|
801
|
+
)
|
|
802
|
+
throw e
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
return res
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
async multicastServers(actionName, params) {
|
|
810
|
+
let res
|
|
811
|
+
if (BROADCAST_ACTIONS[actionName]) {
|
|
812
|
+
this.log.warn(
|
|
813
|
+
`multicastServers prepare trx. actionName: ${actionName} - res: ${JSON.stringify(
|
|
814
|
+
params
|
|
815
|
+
)}`
|
|
816
|
+
)
|
|
817
|
+
const preparedTrx = await asyncWaterfall(
|
|
818
|
+
shuffleArray(
|
|
819
|
+
this.currencyInfo.defaultSettings.apiUrls.map(
|
|
820
|
+
apiUrl => () => this.fioApiRequest(apiUrl, actionName, params, true)
|
|
821
|
+
)
|
|
822
|
+
)
|
|
823
|
+
)
|
|
824
|
+
this.log.warn(
|
|
825
|
+
`multicastServers executePreparedTrx. actionName: ${actionName} - res: ${JSON.stringify(
|
|
826
|
+
preparedTrx
|
|
827
|
+
)}`
|
|
828
|
+
)
|
|
829
|
+
res = await promiseAny(
|
|
830
|
+
shuffleArray(
|
|
831
|
+
this.currencyInfo.defaultSettings.apiUrls.map(apiUrl =>
|
|
832
|
+
this.executePreparedTrx(
|
|
833
|
+
apiUrl,
|
|
834
|
+
EndPoint[ACTIONS_TO_END_POINT_KEYS[actionName]],
|
|
835
|
+
preparedTrx
|
|
836
|
+
)
|
|
837
|
+
)
|
|
838
|
+
)
|
|
839
|
+
)
|
|
840
|
+
this.log.warn(
|
|
841
|
+
`multicastServers res. actionName: ${actionName} - res: ${JSON.stringify(
|
|
842
|
+
res
|
|
843
|
+
)}`
|
|
844
|
+
)
|
|
845
|
+
if (!res) {
|
|
846
|
+
throw new Error('Service is unavailable')
|
|
847
|
+
}
|
|
848
|
+
} else if (actionName === 'getFioNames') {
|
|
849
|
+
res = await promiseNy(
|
|
850
|
+
this.currencyInfo.defaultSettings.apiUrls.map(apiUrl =>
|
|
851
|
+
timeout(this.fioApiRequest(apiUrl, actionName, params), 10000)
|
|
852
|
+
),
|
|
853
|
+
(result) => {
|
|
854
|
+
try {
|
|
855
|
+
return JSON.stringify(asGetFioName(result))
|
|
856
|
+
} catch (e) {
|
|
857
|
+
this.log(
|
|
858
|
+
`getFioNames checkResult function returned error ${e.name} ${e.message}`
|
|
859
|
+
)
|
|
860
|
+
}
|
|
861
|
+
},
|
|
862
|
+
2
|
|
863
|
+
)
|
|
864
|
+
} else {
|
|
865
|
+
res = await asyncWaterfall(
|
|
866
|
+
shuffleArray(
|
|
867
|
+
this.currencyInfo.defaultSettings.apiUrls.map(
|
|
868
|
+
apiUrl => () => this.fioApiRequest(apiUrl, actionName, params)
|
|
869
|
+
)
|
|
870
|
+
)
|
|
871
|
+
)
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
if (res.isError) {
|
|
875
|
+
const error = new FioError(res.errorMessage || res.data.message)
|
|
876
|
+
error.json = res.data.json
|
|
877
|
+
error.list = res.data.list
|
|
878
|
+
error.errorCode = res.data.code
|
|
879
|
+
|
|
880
|
+
throw error
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
return res
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
// Check all account balance and other relevant info
|
|
887
|
+
async checkAccountInnerLoop() {
|
|
888
|
+
const currencyCode = this.currencyInfo.currencyCode
|
|
889
|
+
let nativeAmount = '0'
|
|
890
|
+
if (
|
|
891
|
+
typeof this.walletLocalData.totalBalances[currencyCode] === 'undefined'
|
|
892
|
+
) {
|
|
893
|
+
this.walletLocalData.totalBalances[currencyCode] = '0'
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
// Balance
|
|
897
|
+
try {
|
|
898
|
+
const { balance } = await this.multicastServers('getFioBalance')
|
|
899
|
+
nativeAmount = balance + ''
|
|
900
|
+
} catch (e) {
|
|
901
|
+
this.log('checkAccountInnerLoop error: ' + e)
|
|
902
|
+
nativeAmount = '0'
|
|
903
|
+
}
|
|
904
|
+
this.updateBalance(currencyCode, nativeAmount)
|
|
905
|
+
|
|
906
|
+
// Fio Addresses
|
|
907
|
+
try {
|
|
908
|
+
const result = await this.multicastServers('getFioNames', {
|
|
909
|
+
fioPublicKey: this.walletInfo.keys.publicKey
|
|
910
|
+
})
|
|
911
|
+
|
|
912
|
+
let isChanged = false
|
|
913
|
+
let areAddressesChanged = false
|
|
914
|
+
let areDomainsChanged = false
|
|
915
|
+
|
|
916
|
+
// check addresses
|
|
917
|
+
if (
|
|
918
|
+
result.fio_addresses.length !==
|
|
919
|
+
this.walletLocalData.otherData.fioAddresses.length
|
|
920
|
+
) {
|
|
921
|
+
areAddressesChanged = true
|
|
922
|
+
} else {
|
|
923
|
+
for (const fioAddress of result.fio_addresses) {
|
|
924
|
+
const existedFioAddress =
|
|
925
|
+
this.walletLocalData.otherData.fioAddresses.find(
|
|
926
|
+
existedFioAddress =>
|
|
927
|
+
existedFioAddress.name === fioAddress.fio_address
|
|
928
|
+
)
|
|
929
|
+
if (existedFioAddress) {
|
|
930
|
+
if (existedFioAddress.expiration !== fioAddress.expiration) {
|
|
931
|
+
areAddressesChanged = true
|
|
932
|
+
break
|
|
933
|
+
}
|
|
934
|
+
} else {
|
|
935
|
+
areAddressesChanged = true
|
|
936
|
+
break
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
// check for removed / transferred addresses
|
|
941
|
+
if (!areAddressesChanged) {
|
|
942
|
+
for (const fioAddress of this.walletLocalData.otherData
|
|
943
|
+
.fioAddresses) {
|
|
944
|
+
if (
|
|
945
|
+
result.fio_addresses.findIndex(
|
|
946
|
+
item => item.fio_address === fioAddress.name
|
|
947
|
+
) < 0
|
|
948
|
+
) {
|
|
949
|
+
areAddressesChanged = true
|
|
950
|
+
break
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
// check domains
|
|
957
|
+
if (
|
|
958
|
+
result.fio_domains.length !==
|
|
959
|
+
this.walletLocalData.otherData.fioDomains.length
|
|
960
|
+
) {
|
|
961
|
+
areDomainsChanged = true
|
|
962
|
+
} else {
|
|
963
|
+
for (const fioDomain of result.fio_domains) {
|
|
964
|
+
const existedFioDomain =
|
|
965
|
+
this.walletLocalData.otherData.fioDomains.find(
|
|
966
|
+
existedFioDomain => existedFioDomain.name === fioDomain.fio_domain
|
|
967
|
+
)
|
|
968
|
+
if (existedFioDomain) {
|
|
969
|
+
if (existedFioDomain.expiration !== fioDomain.expiration) {
|
|
970
|
+
areDomainsChanged = true
|
|
971
|
+
break
|
|
972
|
+
}
|
|
973
|
+
if (existedFioDomain.isPublic !== !!fioDomain.is_public) {
|
|
974
|
+
areDomainsChanged = true
|
|
975
|
+
break
|
|
976
|
+
}
|
|
977
|
+
} else {
|
|
978
|
+
areDomainsChanged = true
|
|
979
|
+
break
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
// check for removed / transferred domains
|
|
984
|
+
if (!areDomainsChanged) {
|
|
985
|
+
for (const fioDomain of this.walletLocalData.otherData.fioDomains) {
|
|
986
|
+
if (
|
|
987
|
+
result.fio_domains.findIndex(
|
|
988
|
+
item => item.fio_domain === fioDomain.name
|
|
989
|
+
) < 0
|
|
990
|
+
) {
|
|
991
|
+
areDomainsChanged = true
|
|
992
|
+
break
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
if (areAddressesChanged) {
|
|
999
|
+
isChanged = true
|
|
1000
|
+
this.walletLocalData.otherData.fioAddresses = result.fio_addresses.map(
|
|
1001
|
+
fioAddress => ({
|
|
1002
|
+
name: fioAddress.fio_address,
|
|
1003
|
+
expiration: fioAddress.expiration
|
|
1004
|
+
})
|
|
1005
|
+
)
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
if (areDomainsChanged) {
|
|
1009
|
+
isChanged = true
|
|
1010
|
+
this.walletLocalData.otherData.fioDomains = result.fio_domains.map(
|
|
1011
|
+
fioDomain => ({
|
|
1012
|
+
name: fioDomain.fio_domain,
|
|
1013
|
+
expiration: fioDomain.expiration,
|
|
1014
|
+
isPublic: !!fioDomain.is_public
|
|
1015
|
+
})
|
|
1016
|
+
)
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
if (isChanged) this.localDataDirty()
|
|
1020
|
+
} catch (e) {
|
|
1021
|
+
this.log.warn('checkAccountInnerLoop getFioNames error: ' + e)
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
async approveErroredFioRequests() {
|
|
1026
|
+
for (const fioRequestId in this.walletLocalData.otherData
|
|
1027
|
+
.fioRequestsToApprove) {
|
|
1028
|
+
try {
|
|
1029
|
+
await this.otherMethods.fioAction(
|
|
1030
|
+
'recordObtData',
|
|
1031
|
+
this.walletLocalData.otherData.fioRequestsToApprove[fioRequestId]
|
|
1032
|
+
)
|
|
1033
|
+
} catch (e) {
|
|
1034
|
+
this.log.error(
|
|
1035
|
+
`approveErroredFioRequests recordObtData error: ${JSON.stringify(
|
|
1036
|
+
e
|
|
1037
|
+
)} for ${
|
|
1038
|
+
this.walletLocalData.otherData.fioRequestsToApprove[fioRequestId]
|
|
1039
|
+
}`
|
|
1040
|
+
)
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
async clearBlockchainCache() {
|
|
1046
|
+
await super.clearBlockchainCache()
|
|
1047
|
+
this.walletLocalData.otherData.highestTxHeight = 0
|
|
1048
|
+
this.walletLocalData.otherData.fioAddresses = []
|
|
1049
|
+
this.walletLocalData.otherData.fioDomains = []
|
|
1050
|
+
this.walletLocalData.otherData.fioRequestsToApprove = {}
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
// ****************************************************************************
|
|
1054
|
+
// Public methods
|
|
1055
|
+
// ****************************************************************************
|
|
1056
|
+
|
|
1057
|
+
// This routine is called once a wallet needs to start querying the network
|
|
1058
|
+
async startEngine() {
|
|
1059
|
+
this.engineOn = true
|
|
1060
|
+
this.addToLoop('checkBlockchainInnerLoop', BLOCKCHAIN_POLL_MILLISECONDS)
|
|
1061
|
+
this.addToLoop('checkAccountInnerLoop', ADDRESS_POLL_MILLISECONDS)
|
|
1062
|
+
this.addToLoop('checkTransactionsInnerLoop', TRANSACTION_POLL_MILLISECONDS)
|
|
1063
|
+
this.addToLoop('approveErroredFioRequests', ADDRESS_POLL_MILLISECONDS)
|
|
1064
|
+
super.startEngine()
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
async resyncBlockchain() {
|
|
1068
|
+
await this.killEngine()
|
|
1069
|
+
await this.clearBlockchainCache()
|
|
1070
|
+
await this.startEngine()
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
async makeSpend(edgeSpendInfoIn) {
|
|
1074
|
+
const { edgeSpendInfo, nativeBalance, currencyCode } = super.makeSpend(
|
|
1075
|
+
edgeSpendInfoIn
|
|
1076
|
+
)
|
|
1077
|
+
|
|
1078
|
+
const { otherParams } = edgeSpendInfo
|
|
1079
|
+
let fee
|
|
1080
|
+
if (_optionalChain([otherParams, 'optionalAccess', _ => _.fioAction])) {
|
|
1081
|
+
let feeFioAddress = ''
|
|
1082
|
+
if (FEE_ACTION_MAP[otherParams.fioAction] && otherParams.fioParams) {
|
|
1083
|
+
feeFioAddress =
|
|
1084
|
+
otherParams.fioParams[FEE_ACTION_MAP[otherParams.fioAction].propName]
|
|
1085
|
+
}
|
|
1086
|
+
const feeResponse = await this.multicastServers('getFee', {
|
|
1087
|
+
endPoint: EndPoint[otherParams.fioAction],
|
|
1088
|
+
fioAddress: feeFioAddress
|
|
1089
|
+
})
|
|
1090
|
+
fee = feeResponse.fee
|
|
1091
|
+
} else {
|
|
1092
|
+
// Only query FIO fee if the public address is different from last makeSpend()
|
|
1093
|
+
if (
|
|
1094
|
+
edgeSpendInfo.spendTargets[0].publicAddress ===
|
|
1095
|
+
this.recentFioFee.publicAddress
|
|
1096
|
+
) {
|
|
1097
|
+
fee = this.recentFioFee.fee
|
|
1098
|
+
} else {
|
|
1099
|
+
const feeResponse = await this.multicastServers('getFee', {
|
|
1100
|
+
endPoint: EndPoint.transferTokens
|
|
1101
|
+
})
|
|
1102
|
+
fee = feeResponse.fee
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
const publicAddress = edgeSpendInfo.spendTargets[0].publicAddress
|
|
1107
|
+
const quantity = edgeSpendInfo.spendTargets[0].nativeAmount
|
|
1108
|
+
if (bns.gt(bns.add(quantity, `${fee}`), nativeBalance)) {
|
|
1109
|
+
throw new InsufficientFundsError()
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
if (_optionalChain([otherParams, 'optionalAccess', _2 => _2.fioAction])) {
|
|
1113
|
+
if (
|
|
1114
|
+
['transferFioAddress', 'transferFioDomain'].indexOf(
|
|
1115
|
+
otherParams.fioAction
|
|
1116
|
+
) > -1
|
|
1117
|
+
) {
|
|
1118
|
+
otherParams.fioParams.newOwnerKey = publicAddress
|
|
1119
|
+
}
|
|
1120
|
+
const edgeTransaction = {
|
|
1121
|
+
txid: '',
|
|
1122
|
+
date: 0,
|
|
1123
|
+
currencyCode: this.currencyInfo.currencyCode,
|
|
1124
|
+
blockHeight: 0,
|
|
1125
|
+
nativeAmount: `-${fee}`,
|
|
1126
|
+
networkFee: `${fee}`,
|
|
1127
|
+
parentNetworkFee: '0',
|
|
1128
|
+
signedTx: '',
|
|
1129
|
+
ourReceiveAddresses: [],
|
|
1130
|
+
otherParams: {
|
|
1131
|
+
transactionJson: otherParams
|
|
1132
|
+
},
|
|
1133
|
+
metadata: {
|
|
1134
|
+
notes: ''
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
return edgeTransaction
|
|
1139
|
+
} else {
|
|
1140
|
+
const memo = ''
|
|
1141
|
+
const actor = ''
|
|
1142
|
+
const transactionJson = {
|
|
1143
|
+
actions: [
|
|
1144
|
+
{
|
|
1145
|
+
account: 'fio.token',
|
|
1146
|
+
name: 'trnsfiopubky',
|
|
1147
|
+
authorization: [
|
|
1148
|
+
{
|
|
1149
|
+
actor: actor,
|
|
1150
|
+
permission: 'active'
|
|
1151
|
+
}
|
|
1152
|
+
],
|
|
1153
|
+
data: {
|
|
1154
|
+
from: this.walletInfo.keys.publicKey,
|
|
1155
|
+
to: publicAddress,
|
|
1156
|
+
quantity,
|
|
1157
|
+
memo
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
]
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
const edgeTransaction = {
|
|
1164
|
+
txid: '', // txid
|
|
1165
|
+
date: 0, // date
|
|
1166
|
+
currencyCode, // currencyCode
|
|
1167
|
+
blockHeight: 0, // blockHeight
|
|
1168
|
+
nativeAmount: bns.sub(`-${quantity}`, `${fee}`), // nativeAmount
|
|
1169
|
+
networkFee: `${fee}`, // networkFee
|
|
1170
|
+
ourReceiveAddresses: [], // ourReceiveAddresses
|
|
1171
|
+
signedTx: '0', // signedTx
|
|
1172
|
+
otherParams: {
|
|
1173
|
+
transactionJson
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
this.recentFioFee = { publicAddress, fee }
|
|
1178
|
+
|
|
1179
|
+
return edgeTransaction
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
async signTx(edgeTransaction) {
|
|
1184
|
+
// Do nothing
|
|
1185
|
+
return edgeTransaction
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
async broadcastTx(
|
|
1189
|
+
edgeTransaction
|
|
1190
|
+
) {
|
|
1191
|
+
let trx
|
|
1192
|
+
if (
|
|
1193
|
+
edgeTransaction.otherParams &&
|
|
1194
|
+
edgeTransaction.otherParams.transactionJson &&
|
|
1195
|
+
edgeTransaction.otherParams.transactionJson.fioAction
|
|
1196
|
+
) {
|
|
1197
|
+
trx = await this.otherMethods.fioAction(
|
|
1198
|
+
edgeTransaction.otherParams.transactionJson.fioAction,
|
|
1199
|
+
edgeTransaction.otherParams.transactionJson.fioParams
|
|
1200
|
+
)
|
|
1201
|
+
edgeTransaction.metadata = {
|
|
1202
|
+
notes: trx.transaction_id
|
|
1203
|
+
}
|
|
1204
|
+
} else if (edgeTransaction.spendTargets) {
|
|
1205
|
+
// do transfer
|
|
1206
|
+
const publicAddress = edgeTransaction.spendTargets[0].publicAddress
|
|
1207
|
+
const amount = bns.abs(
|
|
1208
|
+
bns.add(edgeTransaction.nativeAmount, edgeTransaction.networkFee)
|
|
1209
|
+
)
|
|
1210
|
+
trx = await this.multicastServers('transferTokens', {
|
|
1211
|
+
payeeFioPublicKey: publicAddress,
|
|
1212
|
+
amount,
|
|
1213
|
+
maxFee: edgeTransaction.networkFee
|
|
1214
|
+
})
|
|
1215
|
+
} else {
|
|
1216
|
+
throw new Error(
|
|
1217
|
+
'transactionJson not set. FIO transferTokens requires publicAddress'
|
|
1218
|
+
)
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
edgeTransaction.txid = trx.transaction_id
|
|
1222
|
+
edgeTransaction.date = Date.now() / 1000
|
|
1223
|
+
edgeTransaction.blockHeight = trx.block_num
|
|
1224
|
+
this.log.warn(`SUCCESS broadcastTx\n${cleanTxLogs(edgeTransaction)}`)
|
|
1225
|
+
|
|
1226
|
+
return edgeTransaction
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
getFreshAddress(options) {
|
|
1230
|
+
return { publicAddress: this.walletInfo.keys.publicKey }
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
getDisplayPrivateSeed() {
|
|
1234
|
+
let out = ''
|
|
1235
|
+
if (this.walletInfo.keys && this.walletInfo.keys.fioKey) {
|
|
1236
|
+
out += this.walletInfo.keys.fioKey
|
|
1237
|
+
}
|
|
1238
|
+
return out
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
getDisplayPublicSeed() {
|
|
1242
|
+
let out = ''
|
|
1243
|
+
if (this.walletInfo.keys && this.walletInfo.keys.publicKey) {
|
|
1244
|
+
out += this.walletInfo.keys.publicKey
|
|
1245
|
+
}
|
|
1246
|
+
return out
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
export { CurrencyEngine }
|