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.
Files changed (58) hide show
  1. package/CHANGELOG.md +713 -0
  2. package/LICENSE +29 -0
  3. package/README.md +63 -0
  4. package/index.js +3 -0
  5. package/lib/binance/bnbEngine.js +591 -0
  6. package/lib/binance/bnbInfo.js +43 -0
  7. package/lib/binance/bnbPlugin.js +168 -0
  8. package/lib/binance/bnbSchema.js +83 -0
  9. package/lib/binance/bnbTypes.js +39 -0
  10. package/lib/common/engine.js +918 -0
  11. package/lib/common/plugin.js +152 -0
  12. package/lib/common/schema.js +108 -0
  13. package/lib/common/types.js +85 -0
  14. package/lib/common/utils.js +378 -0
  15. package/lib/eos/eosEngine.js +1216 -0
  16. package/lib/eos/eosInfo.js +98 -0
  17. package/lib/eos/eosPlugin.js +314 -0
  18. package/lib/eos/eosSchema.js +190 -0
  19. package/lib/eos/eosTypes.js +88 -0
  20. package/lib/eos/telosInfo.js +94 -0
  21. package/lib/eos/waxInfo.js +95 -0
  22. package/lib/ethereum/etcInfo.js +121 -0
  23. package/lib/ethereum/ethEngine.js +832 -0
  24. package/lib/ethereum/ethInfo.js +1300 -0
  25. package/lib/ethereum/ethMiningFees.js +157 -0
  26. package/lib/ethereum/ethNetwork.js +2195 -0
  27. package/lib/ethereum/ethPlugin.js +377 -0
  28. package/lib/ethereum/ethSchema.js +61 -0
  29. package/lib/ethereum/ethTypes.js +461 -0
  30. package/lib/ethereum/ftminfo.js +102 -0
  31. package/lib/ethereum/rskInfo.js +101 -0
  32. package/lib/fio/fioConst.js +38 -0
  33. package/lib/fio/fioEngine.js +1250 -0
  34. package/lib/fio/fioError.js +38 -0
  35. package/lib/fio/fioInfo.js +72 -0
  36. package/lib/fio/fioPlugin.js +486 -0
  37. package/lib/fio/fioSchema.js +56 -0
  38. package/lib/index.js +44 -0
  39. package/lib/pluginError.js +32 -0
  40. package/lib/react-native/edge-currency-accountbased.js +239635 -0
  41. package/lib/react-native/edge-currency-accountbased.js.map +1 -0
  42. package/lib/react-native-io.js +41 -0
  43. package/lib/stellar/stellarEngine.js +563 -0
  44. package/lib/stellar/stellarInfo.js +37 -0
  45. package/lib/stellar/stellarPlugin.js +215 -0
  46. package/lib/stellar/stellarSchema.js +54 -0
  47. package/lib/stellar/stellarTypes.js +66 -0
  48. package/lib/tezos/tezosEngine.js +497 -0
  49. package/lib/tezos/tezosInfo.js +60 -0
  50. package/lib/tezos/tezosPlugin.js +174 -0
  51. package/lib/tezos/tezosTypes.js +110 -0
  52. package/lib/xrp/xrpEngine.js +583 -0
  53. package/lib/xrp/xrpInfo.js +47 -0
  54. package/lib/xrp/xrpPlugin.js +229 -0
  55. package/lib/xrp/xrpSchema.js +74 -0
  56. package/lib/xrp/xrpTypes.js +38 -0
  57. package/package.json +139 -0
  58. package/postinstall.sh +7 -0
package/LICENSE ADDED
@@ -0,0 +1,29 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2017, Airbitz Inc (dba Edge)
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ * Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ * Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ * Neither the name of the copyright holder nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package/README.md ADDED
@@ -0,0 +1,63 @@
1
+ # Edge Currency Plugin for Account-Based currencies
2
+ [![Build Status][travis-image]][travis-url] [![NPM version][npm-image]][npm-url] [![Dependency Status][daviddm-image]][daviddm-url]
3
+
4
+ [![js-standard-style](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard)
5
+
6
+ Implements Bitcoin send/receive functionality per the spec for crypto currency plugins for [edge-core-js](https://github.com/EdgeApp/edge-core-js)
7
+
8
+ ## Installing
9
+
10
+ npm i edge-currency-accountbased -s
11
+
12
+ ```
13
+ import { stellarCurrencyPluginFactory } from `edge-currency-accountbased`
14
+ import { rippleCurrencyPluginFactory } from `edge-currency-accountbased`
15
+ ```
16
+
17
+ Now you can pass plugins to `edge-core-js`.
18
+
19
+ ```
20
+ const plugins = [
21
+ stellarCurrencyPluginFactory,
22
+ rippleCurrencyPluginFactory
23
+ ]
24
+ const context = makeEdgeContext({
25
+ apiKey: YOUR_API_KEY,
26
+ plugins
27
+ })
28
+ ```
29
+
30
+ ## Contributing
31
+
32
+ You'll need to install Yarn 1.3.2 globally on your machine
33
+
34
+ To run a local version of this repo inside the full Edge Wallet app, clone this repo at the same level as `edge-react-gui`
35
+
36
+ git clone git@github.com:EdgeApp/edge-currency-accountbased.git`
37
+ cd edge-currency-accountbased
38
+ yarn
39
+
40
+ Run `npm run test` to run the unit tests.
41
+
42
+ To use the local cloned version of this repo, `cd edge-react-gui` and run
43
+
44
+ npm run updot edge-currency-accountbased
45
+ npm run postinstall
46
+
47
+ This will copy the necessary files from `edge-currency-accountbased` into the `edge-react-gui/node_modules/edge-currency-accountbased` replacing the npm installed version. This needs to be done after any modifications to `edge-currency-accountbased`
48
+
49
+ ## Adding a New Blockchain / Currency
50
+
51
+ Please note that our team considers (but does not guarantee) PR's to add new currencies / blockchains to this repo's master branch (included into production version of Edge Wallet). Among other requirements the code must satisfy the following guidelines:
52
+ - Rebase of your branch upon this repo's `master` branch. For more info:
53
+ https://github.com/edx/edx-platform/wiki/How-to-Rebase-a-Pull-Request
54
+
55
+ ## License
56
+ BSD 3
57
+
58
+ [npm-image]: https://badge.fury.io/js/edge-currency-ethereum.svg
59
+ [npm-url]: https://npmjs.org/package/edge-currency-ethereum
60
+ [travis-image]: https://travis-ci.org/Airbitz/edge-currency-ethereum.svg?branch=master
61
+ [travis-url]: https://travis-ci.org/Airbitz/edge-currency-ethereum
62
+ [daviddm-image]: https://david-dm.org/Airbitz/edge-currency-ethereum.svg?theme=shields.io
63
+ [daviddm-url]: https://david-dm.org/Airbitz/edge-currency-ethereum
package/index.js ADDED
@@ -0,0 +1,3 @@
1
+ // eslint-disable-next-line no-global-assign
2
+ require = require('esm')(module)
3
+ module.exports = require('./lib/index.js')
@@ -0,0 +1,591 @@
1
+ /**
2
+ * Created by paul on 7/7/17.
3
+ */
4
+ //
5
+
6
+ import BnbApiClient from '@binance-chain/javascript-sdk'
7
+ import { bns } from 'biggystring'
8
+ import {
9
+
10
+
11
+
12
+ InsufficientFundsError
13
+ } from 'edge-core-js/types'
14
+
15
+ import { CurrencyEngine } from '../common/engine.js'
16
+ import {
17
+ asyncWaterfall,
18
+ cleanTxLogs,
19
+ getDenomInfo,
20
+ getOtherParams,
21
+ promiseAny,
22
+ shuffleArray,
23
+ validateObject
24
+ } from '../common/utils.js'
25
+ import { currencyInfo } from './bnbInfo.js'
26
+ // import { calcMiningFee } from './ethMiningFees.js'
27
+ import { BinancePlugin } from './bnbPlugin.js'
28
+ import {
29
+ BinanceApiAccountBalance,
30
+ BinanceApiGetTransactions,
31
+ BinanceApiNodeInfo
32
+ } from './bnbSchema.js'
33
+
34
+
35
+
36
+
37
+
38
+ const PRIMARY_CURRENCY = currencyInfo.currencyCode
39
+ const ACCOUNT_POLL_MILLISECONDS = 20000
40
+ const BLOCKCHAIN_POLL_MILLISECONDS = 20000
41
+ const TRANSACTION_POLL_MILLISECONDS = 3000
42
+ // const UNCONFIRMED_TRANSACTION_POLL_MILLISECONDS = 3000
43
+ // const NETWORKFEES_POLL_MILLISECONDS = 60 * 10 * 1000 // 10 minutes
44
+ const ADDRESS_QUERY_LOOKBACK_TIME = 1000 * 60 * 60 * 24 // ~ one day
45
+ const NUM_TRANSACTIONS_TO_QUERY = 50
46
+ const TIMESTAMP_BEFORE_BNB_LAUNCH = 1554076800000 // 2019-04-01, BNB launched on 2019-04-18
47
+ const NATIVE_UNIT_MULTIPLIER = '100000000'
48
+ const TRANSACTION_QUERY_TIME_WINDOW = 1000 * 60 * 60 * 24 * 2 * 28 // two months
49
+ const NETWORK_FEE_NATIVE_AMOUNT = '37500' // fixed amount for BNB
50
+
51
+
52
+
53
+
54
+
55
+
56
+ // | 'eth_getTransactionCount'
57
+
58
+ // async function broadcastWrapper (promise: Promise<Object>, server: string) {
59
+ // const out = {
60
+ // result: await promise,
61
+ // server
62
+ // }
63
+ // return out
64
+ // }
65
+
66
+ // const dummyTransaction: EdgeTransaction = {
67
+ // txid: '', // txid
68
+ // date: 0, // date
69
+ // currencyCode: 'BNB', // currencyCode
70
+ // blockHeight: 0, // blockHeight
71
+ // nativeAmount: '0', // nativeAmount
72
+ // networkFee: '0', // networkFee
73
+ // ourReceiveAddresses: [], // ourReceiveAddresses
74
+ // signedTx: '0', // signedTx
75
+ // otherParams: {} // otherParams
76
+ // }
77
+
78
+ export class BinanceEngine extends CurrencyEngine {
79
+
80
+ // otherData: BinanceWalletOtherData
81
+ // initOptions: BinanceInitOptions
82
+
83
+ constructor(
84
+ currencyPlugin,
85
+ walletInfo,
86
+ initOptions, // BinanceInitOptions,
87
+ opts // EdgeCurrencyEngineOptions
88
+ ) {
89
+ super(currencyPlugin, walletInfo, opts)
90
+ // if (typeof this.walletInfo.keys.ethereumKey !== 'string') {
91
+ // if (walletInfo.keys.keys && walletInfo.keys.keys.ethereumKey) {
92
+ // this.walletInfo.keys.ethereumKey = walletInfo.keys.keys.ethereumKey
93
+ // }
94
+ // }
95
+ // this.currencyPlugin = currencyPlugin
96
+ // this.initOptions = initOptions
97
+ }
98
+
99
+ async fetchGet(url) {
100
+ const response = await this.io.fetch(url, {
101
+ method: 'GET'
102
+ })
103
+ if (!response.ok) {
104
+ throw new Error(
105
+ `The server returned error code ${response.status} for ${url}`
106
+ )
107
+ }
108
+ return response.json()
109
+ }
110
+
111
+ async checkBlockchainInnerLoop() {
112
+ try {
113
+ const jsonObj = await this.multicastServers(
114
+ 'bnb_blockNumber',
115
+ `/api/v1/node-info`
116
+ )
117
+ const valid = validateObject(jsonObj, BinanceApiNodeInfo)
118
+ if (valid) {
119
+ const blockHeight = jsonObj.sync_info.latest_block_height
120
+ this.log(`Got block height ${blockHeight}`)
121
+ if (this.walletLocalData.blockHeight !== blockHeight) {
122
+ this.checkDroppedTransactionsThrottled()
123
+ this.walletLocalData.blockHeight = blockHeight // Convert to decimal
124
+ this.walletLocalDataDirty = true
125
+ this.currencyEngineCallbacks.onBlockHeightChanged(
126
+ this.walletLocalData.blockHeight
127
+ )
128
+ }
129
+ }
130
+ } catch (err) {
131
+ this.log.error('Error fetching height: ' + err)
132
+ }
133
+ }
134
+
135
+ updateBalance(tk, balance) {
136
+ if (typeof this.walletLocalData.totalBalances[tk] === 'undefined') {
137
+ this.walletLocalData.totalBalances[tk] = '0'
138
+ }
139
+ if (!bns.eq(balance, this.walletLocalData.totalBalances[tk])) {
140
+ this.walletLocalData.totalBalances[tk] = balance
141
+ this.log.warn(tk + ': token Address balance: ' + balance)
142
+ this.currencyEngineCallbacks.onBalanceChanged(tk, balance)
143
+ }
144
+ this.tokenCheckBalanceStatus[tk] = 1
145
+ this.updateOnAddressesChecked()
146
+ }
147
+
148
+ async checkAccountInnerLoop() {
149
+ const address = this.walletLocalData.publicKey
150
+
151
+ try {
152
+ const jsonObj = await this.multicastServers(
153
+ 'bnb_getBalance',
154
+ `/api/v1/account/${address}`
155
+ )
156
+ const valid = validateObject(jsonObj, BinanceApiAccountBalance)
157
+ if (valid) {
158
+ if (jsonObj.balances.length === 0) {
159
+ this.updateBalance('BNB', '0')
160
+ }
161
+ for (const tk of this.walletLocalData.enabledTokens) {
162
+ for (const balance of jsonObj.balances) {
163
+ if (balance.symbol === tk) {
164
+ const denom = getDenomInfo(this.currencyInfo, tk)
165
+ if (!denom) {
166
+ this.log.error(
167
+ `checkAccountInnerLoop Received unsupported currencyCode: ${tk}`
168
+ )
169
+ break
170
+ }
171
+ const nativeAmount = bns.mul(balance.free, denom.multiplier)
172
+ this.updateBalance(tk, nativeAmount)
173
+ }
174
+ }
175
+ }
176
+ }
177
+ } catch (e) {
178
+ // fetching of account balances for uninitiate accounts returns 404 (throws error)
179
+ if (
180
+ this.tokenCheckTransactionsStatus.BNB === 1 &&
181
+ this.transactionList.BNB.length === 0
182
+ ) {
183
+ this.updateBalance('BNB', '0')
184
+ }
185
+ this.log.error(`Error checking BNB address balance`)
186
+ }
187
+ }
188
+
189
+ processBinanceApiTransaction(
190
+ tx,
191
+ currencyCode
192
+ ) {
193
+ let netNativeAmount // Amount received into wallet
194
+ const ourReceiveAddresses = []
195
+ const nativeNetworkFee = bns.mul(tx.txFee, NATIVE_UNIT_MULTIPLIER) // always denominated in BNB
196
+ const nativeValue = bns.mul(tx.value, NATIVE_UNIT_MULTIPLIER)
197
+ if (
198
+ tx.fromAddr.toLowerCase() === this.walletLocalData.publicKey.toLowerCase()
199
+ ) {
200
+ // if it's a send to one's self
201
+ if (tx.fromAddr.toLowerCase() === tx.toAddr.toLowerCase()) {
202
+ // Spend to self. netNativeAmount is just the fee
203
+ netNativeAmount = bns.mul(nativeNetworkFee, '-1')
204
+ } else {
205
+ netNativeAmount = bns.sub('0', nativeValue)
206
+
207
+ // For spends, include the network fee in the transaction amount
208
+ netNativeAmount = bns.sub(netNativeAmount, nativeNetworkFee)
209
+ }
210
+ } else {
211
+ // Receive transaction
212
+ netNativeAmount = bns.add('0', nativeValue)
213
+ // ourReceiveAddresses.push(this.walletLocalData.publicKey.toLowerCase())
214
+ }
215
+
216
+ const otherParams = {
217
+ code: tx.code,
218
+ orderId: tx.orderId
219
+ }
220
+
221
+ let blockHeight = tx.blockHeight
222
+ if (blockHeight < 0) blockHeight = 0
223
+ const unixTimestamp = new Date(tx.timeStamp)
224
+ const edgeTransaction = {
225
+ txid: tx.txHash,
226
+ date: unixTimestamp.getTime(),
227
+ currencyCode,
228
+ blockHeight,
229
+ nativeAmount: netNativeAmount,
230
+ networkFee: nativeNetworkFee,
231
+ ourReceiveAddresses, // blank if you sent money otherwise array of addresses that are yours in this transaction
232
+ signedTx: '',
233
+ otherParams
234
+ }
235
+
236
+ this.addTransaction(currencyCode, edgeTransaction)
237
+ }
238
+
239
+ async checkTransactionsFetch(
240
+ startTime,
241
+ currencyCode
242
+ ) {
243
+ const address = this.walletLocalData.publicKey
244
+ let checkAddressSuccess = true
245
+ let start = startTime
246
+ let end = 0
247
+ const now = Date.now()
248
+ try {
249
+ // this.log('checkTransactionsFetch start of while loop')
250
+ while (end !== now && checkAddressSuccess) {
251
+ // loop from startTime to current time by 3-month increments
252
+ end = start + TRANSACTION_QUERY_TIME_WINDOW
253
+ if (end > now) end = now
254
+ // this.log('checkTransactionsFetch outer loop: ', start, ' and end: ', end)
255
+ for (let offset = 0; ; offset += NUM_TRANSACTIONS_TO_QUERY) {
256
+ // this.log('checkTransactionsFetch inner loop, offset is: ', offset)
257
+ // loop by 50-tx increments
258
+ const baseUrl = `/api/v1/transactions?address=${address}&txType=TRANSFER&limit=${NUM_TRANSACTIONS_TO_QUERY}`
259
+ const finalUrl =
260
+ baseUrl +
261
+ `&offset=${offset}&startTime=${start}&endTime=${end}&txAsset=${currencyCode}`
262
+ const transactionsResults = await this.multicastServers(
263
+ 'bnb_getTransactions',
264
+ finalUrl
265
+ )
266
+ const valid = validateObject(
267
+ transactionsResults,
268
+ BinanceApiGetTransactions
269
+ )
270
+ if (valid) {
271
+ for (const transaction of transactionsResults.tx) {
272
+ // shuold we process extra transaction for native BNB fees?
273
+ this.processBinanceApiTransaction(transaction, currencyCode)
274
+ }
275
+ if (transactionsResults.tx.length < NUM_TRANSACTIONS_TO_QUERY) {
276
+ break
277
+ }
278
+ } else {
279
+ checkAddressSuccess = false
280
+ this.log.error(
281
+ 'checkTransactionsFetch inner loop invalid query results'
282
+ )
283
+ break
284
+ }
285
+ }
286
+ start = end
287
+ }
288
+ } catch (e) {
289
+ this.log.error(
290
+ `Error checkTransactionsFetch ${currencyCode}: ${this.walletLocalData.publicKey}`,
291
+ e
292
+ )
293
+ }
294
+
295
+ if (checkAddressSuccess) {
296
+ this.tokenCheckTransactionsStatus[currencyCode] = 1
297
+ // this.updateOnAddressesChecked()
298
+ return true
299
+ } else {
300
+ return false
301
+ }
302
+ }
303
+
304
+ async checkTransactionsInnerLoop() {
305
+ const blockHeight = Date.now()
306
+ let startTime = TIMESTAMP_BEFORE_BNB_LAUNCH
307
+ const promiseArray = []
308
+
309
+ if (
310
+ this.walletLocalData.lastAddressQueryHeight > ADDRESS_QUERY_LOOKBACK_TIME
311
+ ) {
312
+ // Only query for transactions as far back as ADDRESS_QUERY_LOOKBACK_TIME from the last time we queried transactions
313
+ startTime =
314
+ this.walletLocalData.lastAddressQueryHeight -
315
+ ADDRESS_QUERY_LOOKBACK_TIME
316
+ }
317
+
318
+ for (const currencyCode of this.walletLocalData.enabledTokens) {
319
+ promiseArray.push(this.checkTransactionsFetch(startTime, currencyCode))
320
+ }
321
+
322
+ let resultArray = []
323
+ try {
324
+ resultArray = await Promise.all(promiseArray)
325
+ } catch (e) {
326
+ this.log.error('Failed to query transactions', e.name, e.message)
327
+ }
328
+ let successCount = 0
329
+ for (const r of resultArray) {
330
+ if (r) successCount++
331
+ }
332
+ if (successCount === promiseArray.length) {
333
+ // should be time
334
+ this.walletLocalData.lastAddressQueryHeight = blockHeight
335
+ }
336
+ if (this.transactionsChangedArray.length > 0) {
337
+ this.currencyEngineCallbacks.onTransactionsChanged(
338
+ this.transactionsChangedArray
339
+ )
340
+ this.transactionsChangedArray = []
341
+ }
342
+ }
343
+
344
+ async multicastServers(func, ...params) {
345
+ let out = { result: '', server: 'no server' }
346
+ let funcs
347
+ switch (func) {
348
+ case 'bnb_broadcastTx': {
349
+ const promises = []
350
+ const broadcastServers =
351
+ this.currencyInfo.defaultSettings.otherSettings.binanceApiServers
352
+ for (const bnbServer of broadcastServers) {
353
+ const endpoint = `${bnbServer}/api/v1/broadcast?sync=true`
354
+ promises.push(
355
+ this.io.fetch(endpoint, {
356
+ method: 'POST',
357
+ body: params[0],
358
+ headers: {
359
+ 'content-type': 'text/plain'
360
+ }
361
+ })
362
+ )
363
+ }
364
+ const response = await promiseAny(promises)
365
+ const result = await response.json()
366
+ if (result[0] && result[0].ok && result[0].code === 0) {
367
+ this.log(`multicastServers ${func} ${JSON.stringify(out)} won`)
368
+ return {
369
+ result,
370
+ server: 'irrelevant'
371
+ }
372
+ } else {
373
+ throw new Error('send fail with error: ' + result.message)
374
+ }
375
+ }
376
+
377
+ case 'bnb_blockNumber':
378
+ case 'bnb_getBalance':
379
+ case 'bnb_getTransactions':
380
+ funcs =
381
+ this.currencyInfo.defaultSettings.otherSettings.binanceApiServers.map(
382
+ server => async () => {
383
+ const result = await this.fetchGet(server + params[0])
384
+ if (typeof result !== 'object') {
385
+ const msg = `Invalid return value ${func} in ${server}`
386
+ this.log.error(msg)
387
+ throw new Error(msg)
388
+ }
389
+ return { server, result }
390
+ }
391
+ )
392
+ // Randomize array
393
+ funcs = shuffleArray(funcs)
394
+ out = await asyncWaterfall(funcs)
395
+ break
396
+ }
397
+ this.log(`multicastServers ${func} ${out.server} won`)
398
+
399
+ return out.result
400
+ }
401
+
402
+ // async clearBlockchainCache () {
403
+ // await super.clearBlockchainCache()
404
+ // this.otherData.nextNonce = '0'
405
+ // this.otherData.unconfirmedNextNonce = '0'
406
+ // }
407
+
408
+ // // ****************************************************************************
409
+ // // Public methods
410
+ // // ****************************************************************************
411
+
412
+ async startEngine() {
413
+ this.engineOn = true
414
+ this.addToLoop('checkBlockchainInnerLoop', BLOCKCHAIN_POLL_MILLISECONDS)
415
+ this.addToLoop('checkAccountInnerLoop', ACCOUNT_POLL_MILLISECONDS)
416
+ // this.addToLoop('checkUpdateNetworkFees', NETWORKFEES_POLL_MILLISECONDS)
417
+ this.addToLoop('checkTransactionsInnerLoop', TRANSACTION_POLL_MILLISECONDS)
418
+ // this.addToLoop(
419
+ // 'checkUnconfirmedTransactionsInnerLoop',
420
+ // UNCONFIRMED_TRANSACTION_POLL_MILLISECONDS
421
+ // )
422
+ super.startEngine()
423
+ }
424
+
425
+ async resyncBlockchain() {
426
+ await this.killEngine()
427
+ await this.clearBlockchainCache()
428
+ await this.startEngine()
429
+ }
430
+
431
+ async makeSpend(edgeSpendInfoIn) {
432
+ const { edgeSpendInfo, currencyCode } = super.makeSpend(edgeSpendInfoIn)
433
+
434
+ const spendTarget = edgeSpendInfo.spendTargets[0]
435
+ const publicAddress = spendTarget.publicAddress
436
+ const data =
437
+ spendTarget.otherParams != null ? spendTarget.otherParams.data : undefined
438
+
439
+ let otherParams = {}
440
+
441
+ if (currencyCode === PRIMARY_CURRENCY) {
442
+ const bnbParams = {
443
+ from: [this.walletLocalData.publicKey],
444
+ to: [publicAddress],
445
+ errorVal: 0,
446
+ tokenRecipientAddress: null,
447
+ data: data
448
+ }
449
+ otherParams = bnbParams
450
+ } else {
451
+ let contractAddress = ''
452
+ if (data) {
453
+ contractAddress = publicAddress
454
+ } else {
455
+ const tokenInfo = this.getTokenInfo(currencyCode)
456
+ if (!tokenInfo || typeof tokenInfo.contractAddress !== 'string') {
457
+ throw new Error(
458
+ 'Error: Token not supported or invalid contract address'
459
+ )
460
+ }
461
+
462
+ contractAddress = tokenInfo.contractAddress
463
+ }
464
+
465
+ const bnbParams = {
466
+ from: [this.walletLocalData.publicKey],
467
+ to: [contractAddress],
468
+ errorVal: 0,
469
+ tokenRecipientAddress: publicAddress,
470
+ data: data
471
+ }
472
+ otherParams = bnbParams
473
+ }
474
+ if (
475
+ edgeSpendInfo.spendTargets[0].otherParams &&
476
+ edgeSpendInfo.spendTargets[0].otherParams.uniqueIdentifier
477
+ ) {
478
+ otherParams.memo =
479
+ edgeSpendInfo.spendTargets[0].otherParams.uniqueIdentifier
480
+ }
481
+
482
+ const nativeNetworkFee = NETWORK_FEE_NATIVE_AMOUNT
483
+ const ErrorInsufficientFundsMoreBnb = new Error(
484
+ 'Insufficient BNB for transaction fee'
485
+ )
486
+ ErrorInsufficientFundsMoreBnb.name = 'ErrorInsufficientFundsMoreBnb'
487
+
488
+ let nativeAmount = edgeSpendInfo.spendTargets[0].nativeAmount
489
+ const balanceBnb =
490
+ this.walletLocalData.totalBalances[this.currencyInfo.currencyCode]
491
+
492
+ let totalTxAmount = '0'
493
+ totalTxAmount = bns.add(nativeAmount, nativeNetworkFee)
494
+ if (bns.gt(totalTxAmount, balanceBnb)) {
495
+ throw new InsufficientFundsError()
496
+ }
497
+ nativeAmount = bns.mul(totalTxAmount, '-1')
498
+
499
+ // **********************************
500
+ // Create the unsigned EdgeTransaction
501
+
502
+ const edgeTransaction = {
503
+ txid: '', // txid
504
+ date: 0, // date
505
+ currencyCode, // currencyCode
506
+ blockHeight: 0, // blockHeight
507
+ nativeAmount, // nativeAmount
508
+ networkFee: nativeNetworkFee, // networkFee, supposedly fixed
509
+ ourReceiveAddresses: [], // ourReceiveAddresses
510
+ signedTx: '', // signedTx
511
+ otherParams // otherParams
512
+ }
513
+
514
+ return edgeTransaction
515
+ }
516
+
517
+ async signTx(edgeTransaction) {
518
+ const otherParams = getOtherParams(edgeTransaction)
519
+
520
+ const bnbClient = new BnbApiClient(
521
+ currencyInfo.defaultSettings.otherSettings.binanceApiServers[0]
522
+ )
523
+ bnbClient.chooseNetwork('mainnet')
524
+ const privKey = this.walletInfo.keys.binanceKey
525
+ await bnbClient.setPrivateKey(privKey)
526
+ await bnbClient.initChain()
527
+ const currencyCode = edgeTransaction.currencyCode
528
+ const spendAmount = bns.add(
529
+ edgeTransaction.nativeAmount,
530
+ NETWORK_FEE_NATIVE_AMOUNT
531
+ )
532
+ const amount = spendAmount.replace('-', '')
533
+ const denom = getDenomInfo(this.currencyInfo, currencyCode)
534
+ if (!denom) {
535
+ this.log.error(
536
+ `signTx Received unsupported currencyCode: ${currencyCode}`
537
+ )
538
+ throw new Error(`Received unsupported currencyCode: ${currencyCode}`)
539
+ }
540
+ const nativeAmountString = parseInt(amount) / parseInt(denom.multiplier)
541
+ const nativeAmount = parseFloat(nativeAmountString)
542
+ // identity function, overriding library's version
543
+ bnbClient._broadcastDelegate = x => {
544
+ return x
545
+ }
546
+ // WILL NOT ACTUALLY TRANSFER! That will be done in this.broadcastTx
547
+ const signedTx = await bnbClient.transfer(
548
+ otherParams.from[0],
549
+ otherParams.to[0],
550
+ nativeAmount,
551
+ currencyCode,
552
+ otherParams.memo
553
+ )
554
+ otherParams.serializedTx = signedTx.serialize()
555
+ this.log.warn(`signTx\n${cleanTxLogs(edgeTransaction)}`)
556
+ return edgeTransaction
557
+ }
558
+
559
+ async broadcastTx(
560
+ edgeTransaction
561
+ ) {
562
+ const otherParams = getOtherParams(edgeTransaction)
563
+
564
+ const bnbSignedTransaction = otherParams.serializedTx
565
+ const response = await this.multicastServers(
566
+ 'bnb_broadcastTx',
567
+ bnbSignedTransaction
568
+ )
569
+ if (response.result[0] && response.result[0].ok) {
570
+ this.log.warn(`SUCCESS broadcastTx\n${cleanTxLogs(edgeTransaction)}`)
571
+ edgeTransaction.txid = response.result[0].hash
572
+ }
573
+ return edgeTransaction
574
+ }
575
+
576
+ getDisplayPrivateSeed() {
577
+ if (this.walletInfo.keys && this.walletInfo.keys.binanceMnemonic) {
578
+ return this.walletInfo.keys.binanceMnemonic
579
+ }
580
+ return ''
581
+ }
582
+
583
+ getDisplayPublicSeed() {
584
+ if (this.walletInfo.keys && this.walletInfo.keys.publicKey) {
585
+ return this.walletInfo.keys.publicKey
586
+ }
587
+ return ''
588
+ }
589
+ }
590
+
591
+ export { CurrencyEngine }