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
@@ -0,0 +1,497 @@
1
+ //
2
+ import { bns } from 'biggystring'
3
+ import {
4
+
5
+
6
+
7
+
8
+
9
+ InsufficientFundsError,
10
+ NoAmountSpecifiedError
11
+ } from 'edge-core-js/types'
12
+ import { eztz } from 'eztz.js'
13
+
14
+ import { CurrencyEngine } from '../common/engine.js'
15
+ import {
16
+ asyncWaterfall,
17
+ cleanTxLogs,
18
+ getOtherParams,
19
+ makeMutex,
20
+ promiseAny
21
+ } from '../common/utils.js'
22
+ import { TezosPlugin } from '../tezos/tezosPlugin.js'
23
+ import { currencyInfo } from './tezosInfo.js'
24
+ import {
25
+
26
+
27
+
28
+
29
+ asXtzGetTransaction
30
+ } from './tezosTypes.js'
31
+
32
+ const ADDRESS_POLL_MILLISECONDS = 15000
33
+ const BLOCKCHAIN_POLL_MILLISECONDS = 30000
34
+ const TRANSACTION_POLL_MILLISECONDS = 5000
35
+
36
+ const makeSpendMutex = makeMutex()
37
+
38
+ const PRIMARY_CURRENCY = currencyInfo.currencyCode
39
+
40
+
41
+
42
+
43
+
44
+
45
+
46
+
47
+
48
+ export class TezosEngine extends CurrencyEngine {
49
+
50
+
51
+
52
+ constructor(
53
+ currencyPlugin,
54
+ walletInfo,
55
+ opts,
56
+ fetchCors
57
+ ) {
58
+ super(currencyPlugin, walletInfo, opts)
59
+ this.tezosPlugin = currencyPlugin
60
+ this.fetchCors = fetchCors
61
+ }
62
+
63
+ async multicastServers(func, ...params) {
64
+ let out = { result: '', server: 'no server' }
65
+ let funcs
66
+ switch (func) {
67
+ // Functions that should waterfall from top to low priority servers
68
+ case 'getHead': {
69
+ // relevant nodes, disabling first node due to caching / polling issue
70
+ // need to re-enable once that nodes issue is fixed
71
+ const nonCachedNodes = this.tezosPlugin.tezosRpcNodes
72
+ funcs = nonCachedNodes.map(server => async () => {
73
+ const result = await this.io
74
+ .fetch(server + '/chains/main/blocks/head/header')
75
+ .then(function (response) {
76
+ return response.json()
77
+ })
78
+ .then(function (json) {
79
+ return json
80
+ })
81
+ return { server, result }
82
+ })
83
+ out = await asyncWaterfall(funcs)
84
+ break
85
+ }
86
+
87
+ case 'getBalance': {
88
+ const usableNodes = this.tezosPlugin.tezosRpcNodes
89
+ funcs = usableNodes.map(server => async () => {
90
+ eztz.node.setProvider(server)
91
+ const result = await eztz.rpc.getBalance(params[0])
92
+ return { server, result }
93
+ })
94
+ out = await asyncWaterfall(funcs)
95
+ break
96
+ }
97
+
98
+ case 'getNumberOfOperations':
99
+ funcs = this.tezosPlugin.tezosApiServers.map(server => async () => {
100
+ const result = await this.fetchCors(
101
+ `${server}/v1/accounts/${params[0]}`
102
+ )
103
+ .then(function (response) {
104
+ return response.json()
105
+ })
106
+ .then(function (json) {
107
+ return json.numTransactions
108
+ })
109
+ return { server, result }
110
+ })
111
+ out = await asyncWaterfall(funcs)
112
+ break
113
+
114
+ case 'getTransactions':
115
+ funcs = this.tezosPlugin.tezosApiServers.map(server => async () => {
116
+ const pagination = /tzkt/.test(server)
117
+ ? ''
118
+ : `&p='${params[1]}&number=50`
119
+ const result = await this.fetchCors(
120
+ `${server}/v1/accounts/${params[0]}/operations?type=transaction` +
121
+ pagination
122
+ ).then(function (response) {
123
+ return response.json()
124
+ })
125
+ return { server, result }
126
+ })
127
+ out = await asyncWaterfall(funcs)
128
+ break
129
+
130
+ case 'createTransaction':
131
+ funcs = this.tezosPlugin.tezosRpcNodes.map(server => async () => {
132
+ eztz.node.setProvider(server)
133
+ const result = await eztz.rpc
134
+ .transfer(
135
+ params[0],
136
+ params[1],
137
+ params[2],
138
+ params[3],
139
+ params[4],
140
+ null,
141
+ this.currencyInfo.defaultSettings.limit.gas,
142
+ this.currencyInfo.defaultSettings.limit.storage,
143
+ this.currencyInfo.defaultSettings.fee.reveal
144
+ )
145
+ .then(function (response) {
146
+ return response
147
+ })
148
+ return { server, result }
149
+ })
150
+ out = await asyncWaterfall(funcs)
151
+ break
152
+
153
+ // Functions that should multicast to all servers
154
+ case 'injectOperation': {
155
+ let preApplyError = ''
156
+ funcs = this.tezosPlugin.tezosRpcNodes.map(server => async () => {
157
+ eztz.node.setProvider(server)
158
+ const result = await eztz.rpc
159
+ .inject(params[0], params[1])
160
+ .catch((e) => {
161
+ this.log.error(
162
+ 'Error when injection operation: ' + e.name + e.message
163
+ )
164
+ const errorMessage = this.formatError(e)
165
+ if (!preApplyError && errorMessage !== '') {
166
+ preApplyError = errorMessage
167
+ }
168
+ throw e
169
+ })
170
+ // Preapply passed -> Broadcast to all remaining nodes in the waterfall
171
+ this.multicastServers('silentInjection', server, params[1])
172
+ return { server, result }
173
+ })
174
+ out = await asyncWaterfall(funcs).catch((e) => {
175
+ this.log.error('Error from waterfall: ' + e.name + e.message)
176
+ if (preApplyError !== '') {
177
+ throw new Error(preApplyError)
178
+ } else {
179
+ throw e
180
+ }
181
+ })
182
+ break
183
+ }
184
+
185
+ case 'silentInjection': {
186
+ const index = this.tezosPlugin.tezosRpcNodes.indexOf(params[0])
187
+ const remainingRpcNodes = this.tezosPlugin.tezosRpcNodes.slice(
188
+ index + 1
189
+ )
190
+ out = await promiseAny(
191
+ remainingRpcNodes.map(async server => {
192
+ eztz.node.setProvider(server)
193
+ const result = await eztz.rpc.silentInject(params[1])
194
+ this.log.warn('Injected silently to: ' + server)
195
+ return { server, result }
196
+ })
197
+ )
198
+ break
199
+ }
200
+ }
201
+ this.log(
202
+ `XTZ multicastServers ${func} ${out.server} won with result ${out.result}`
203
+ )
204
+ return out.result
205
+ }
206
+
207
+ formatError(e) {
208
+ if (typeof e === 'string') {
209
+ return e
210
+ }
211
+ try {
212
+ if (
213
+ e.error &&
214
+ e.error === 'Operation Failed' &&
215
+ e.errors &&
216
+ e.errors[0].id
217
+ ) {
218
+ return 'Failed in preapply with an error code (' + e.errors[0].id + ')'
219
+ } else if (e[0] && e[0].kind && e[0].kind === 'branch' && e[0].id) {
220
+ return 'Failed in preapply with an error code (' + e[0].id + ')'
221
+ }
222
+ } catch (e) {}
223
+ return ''
224
+ }
225
+
226
+ processTezosTransaction(tx) {
227
+ const transaction = asXtzGetTransaction(tx)
228
+ const pkh = this.walletLocalData.publicKey
229
+ const ourReceiveAddresses = []
230
+ const currencyCode = PRIMARY_CURRENCY
231
+ const date = new Date(transaction.timestamp).getTime() / 1000
232
+ const blockHeight = transaction.level
233
+ let nativeAmount = transaction.amount.toString()
234
+ const networkFee = (
235
+ transaction.bakerFee + transaction.allocationFee
236
+ ).toString()
237
+ const failedOperation = transaction.status === 'failed'
238
+ if (pkh === transaction.target.address) {
239
+ ourReceiveAddresses.push(pkh)
240
+ if (transaction.sender.address === pkh) {
241
+ nativeAmount = '-' + networkFee
242
+ }
243
+ } else {
244
+ nativeAmount = '-' + bns.add(nativeAmount, networkFee)
245
+ }
246
+ const edgeTransaction = {
247
+ txid: tx.hash,
248
+ date,
249
+ currencyCode,
250
+ blockHeight,
251
+ nativeAmount,
252
+ networkFee,
253
+ ourReceiveAddresses,
254
+ signedTx: '',
255
+ otherParams: {}
256
+ }
257
+ if (!failedOperation) {
258
+ this.addTransaction(currencyCode, edgeTransaction)
259
+ }
260
+ }
261
+
262
+ async checkTransactionsInnerLoop() {
263
+ const pkh = this.walletLocalData.publicKey
264
+ if (!this.otherData.numberTransactions) {
265
+ this.otherData.numberTransactions = 0
266
+ }
267
+ const num = await this.multicastServers('getNumberOfOperations', pkh)
268
+ if (num !== this.otherData.numberTransactions) {
269
+ let txs = []
270
+ let page = 0
271
+ let transactions
272
+ this.tokenCheckTransactionsStatus.XTZ = 0.5
273
+ do {
274
+ transactions = await this.multicastServers(
275
+ 'getTransactions',
276
+ pkh,
277
+ page++
278
+ )
279
+ txs = txs.concat(transactions)
280
+ } while (transactions.length > 0 && page < 10)
281
+ for (const tx of txs) {
282
+ this.processTezosTransaction(tx)
283
+ }
284
+ if (this.transactionsChangedArray.length > 0) {
285
+ this.currencyEngineCallbacks.onTransactionsChanged(
286
+ this.transactionsChangedArray
287
+ )
288
+ this.transactionsChangedArray = []
289
+ }
290
+ this.otherData.numberTransactions = num
291
+ this.walletLocalDataDirty = true
292
+ }
293
+ this.tokenCheckTransactionsStatus.XTZ = 1
294
+ this.updateOnAddressesChecked()
295
+ }
296
+
297
+ async checkUnconfirmedTransactionsFetch() {}
298
+
299
+ // Check all account balance and other relevant info
300
+ async checkAccountInnerLoop() {
301
+ this.tokenCheckBalanceStatus.XTZ = 0
302
+ const currencyCode = PRIMARY_CURRENCY
303
+ const pkh = this.walletLocalData.publicKey
304
+ if (
305
+ typeof this.walletLocalData.totalBalances[currencyCode] === 'undefined'
306
+ ) {
307
+ this.walletLocalData.totalBalances[currencyCode] = '0'
308
+ }
309
+ const balance = await this.multicastServers('getBalance', pkh)
310
+ if (this.walletLocalData.totalBalances[currencyCode] !== balance) {
311
+ this.walletLocalData.totalBalances[currencyCode] = balance
312
+ this.log.warn(`Updated ${currencyCode} balance ${balance}`)
313
+ this.currencyEngineCallbacks.onBalanceChanged(currencyCode, balance)
314
+ }
315
+ this.tokenCheckBalanceStatus.XTZ = 1
316
+ }
317
+
318
+ async checkBlockchainInnerLoop() {
319
+ const head = await this.multicastServers('getHead')
320
+ const blockHeight = head.level
321
+ if (this.walletLocalData.blockHeight !== blockHeight) {
322
+ this.walletLocalData.blockHeight = blockHeight
323
+ this.walletLocalDataDirty = true
324
+ this.currencyEngineCallbacks.onBlockHeightChanged(
325
+ this.walletLocalData.blockHeight
326
+ )
327
+ }
328
+ }
329
+
330
+ async clearBlockchainCache() {
331
+ await super.clearBlockchainCache()
332
+ }
333
+
334
+ async isBurn(op) {
335
+ if (op.kind === 'origination') {
336
+ return true
337
+ }
338
+ if (op.kind === 'transaction' && op.destination.slice(0, 2) === 'tz') {
339
+ const balance = await this.multicastServers('getBalance', op.destination)
340
+ if (balance === '0') {
341
+ return true
342
+ }
343
+ }
344
+ return false
345
+ }
346
+ // ****************************************************************************
347
+ // Public methods
348
+ // ****************************************************************************
349
+
350
+ async startEngine() {
351
+ this.engineOn = true
352
+ this.addToLoop('checkBlockchainInnerLoop', BLOCKCHAIN_POLL_MILLISECONDS)
353
+ this.addToLoop('checkAccountInnerLoop', ADDRESS_POLL_MILLISECONDS)
354
+ this.addToLoop('checkTransactionsInnerLoop', TRANSACTION_POLL_MILLISECONDS)
355
+ super.startEngine()
356
+ }
357
+
358
+ async resyncBlockchain() {
359
+ await this.killEngine()
360
+ await this.clearBlockchainCache()
361
+ await this.startEngine()
362
+ }
363
+
364
+ async makeSpend(edgeSpendInfoIn) {
365
+ return makeSpendMutex(() => this.makeSpendInner(edgeSpendInfoIn))
366
+ }
367
+
368
+ async makeSpendInner(
369
+ edgeSpendInfoIn
370
+ ) {
371
+ const { edgeSpendInfo, currencyCode, nativeBalance, denom } =
372
+ super.makeSpend(edgeSpendInfoIn)
373
+ if (edgeSpendInfo.spendTargets.length !== 1) {
374
+ throw new Error('Error: only one output allowed')
375
+ }
376
+ const publicAddress = edgeSpendInfo.spendTargets[0].publicAddress
377
+ let nativeAmount = '0'
378
+ if (typeof edgeSpendInfo.spendTargets[0].nativeAmount === 'string') {
379
+ nativeAmount = edgeSpendInfo.spendTargets[0].nativeAmount
380
+ } else {
381
+ throw new NoAmountSpecifiedError()
382
+ }
383
+ if (bns.eq(nativeAmount, '0')) {
384
+ throw new NoAmountSpecifiedError()
385
+ }
386
+ const keys = {
387
+ pk: this.walletInfo.keys.publicKeyEd,
388
+ pkh: this.walletInfo.keys.publicKey,
389
+ sk: false
390
+ }
391
+ let ops
392
+ let resendCounter = 0
393
+ let error
394
+ do {
395
+ try {
396
+ ops = await this.multicastServers(
397
+ 'createTransaction',
398
+ keys.pkh,
399
+ keys,
400
+ publicAddress,
401
+ bns.div(nativeAmount, denom.multiplier, 6),
402
+ this.currencyInfo.defaultSettings.fee.transaction
403
+ )
404
+ } catch (e) {
405
+ error = e
406
+ }
407
+ } while (
408
+ (typeof ops === 'undefined' || ops.opOb.contents.length > 2) &&
409
+ resendCounter++ < 5
410
+ )
411
+ if (typeof ops === 'undefined') {
412
+ throw error
413
+ }
414
+ let networkFee = '0'
415
+ for (const operation of ops.opOb.contents) {
416
+ networkFee = bns.add(networkFee, operation.fee)
417
+ const burn = await this.isBurn(operation)
418
+ if (burn) {
419
+ networkFee = bns.add(
420
+ networkFee,
421
+ this.currencyInfo.defaultSettings.fee.burn
422
+ )
423
+ }
424
+ }
425
+ nativeAmount = bns.add(nativeAmount, networkFee)
426
+ if (bns.gt(nativeAmount, nativeBalance)) {
427
+ throw new InsufficientFundsError()
428
+ }
429
+ nativeAmount = '-' + nativeAmount
430
+
431
+ const edgeTransaction = {
432
+ txid: '',
433
+ date: 0,
434
+ currencyCode,
435
+ blockHeight: 0,
436
+ nativeAmount,
437
+ networkFee,
438
+ ourReceiveAddresses: [],
439
+ signedTx: '',
440
+ otherParams: {
441
+ idInternal: 0,
442
+ fromAddress: this.walletLocalData.publicKey,
443
+ toAddress: publicAddress,
444
+ fullOp: ops
445
+ }
446
+ }
447
+ return edgeTransaction
448
+ }
449
+
450
+ async signTx(edgeTransaction) {
451
+ const otherParams = getOtherParams(edgeTransaction)
452
+
453
+ if (edgeTransaction.signedTx === '') {
454
+ const sk = this.walletInfo.keys.privateKey
455
+ const signed = eztz.crypto.sign(
456
+ otherParams.fullOp.opbytes,
457
+ sk,
458
+ eztz.watermark.generic
459
+ )
460
+ otherParams.fullOp.opbytes = signed.sbytes
461
+ otherParams.fullOp.opOb.signature = signed.edsig
462
+ edgeTransaction.signedTx = signed.sbytes
463
+ }
464
+ this.log.warn(`signTx\n${cleanTxLogs(edgeTransaction)}`)
465
+ return edgeTransaction
466
+ }
467
+
468
+ async broadcastTx(
469
+ edgeTransaction
470
+ ) {
471
+ const otherParams = getOtherParams(edgeTransaction)
472
+
473
+ const opBytes = otherParams.fullOp.opbytes
474
+ const opOb = otherParams.fullOp.opOb
475
+ const result = await this.multicastServers('injectOperation', opOb, opBytes)
476
+ edgeTransaction.txid = result.hash
477
+ edgeTransaction.date = Date.now() / 1000
478
+ this.log.warn(`SUCCESS broadcastTx\n${cleanTxLogs(edgeTransaction)}`)
479
+ return edgeTransaction
480
+ }
481
+
482
+ getDisplayPrivateSeed() {
483
+ if (this.walletInfo.keys && this.walletInfo.keys.mnemonic) {
484
+ return this.walletInfo.keys.mnemonic
485
+ }
486
+ return ''
487
+ }
488
+
489
+ getDisplayPublicSeed() {
490
+ if (this.walletInfo.keys && this.walletInfo.keys.publicKey) {
491
+ return this.walletInfo.keys.publicKey
492
+ }
493
+ return ''
494
+ }
495
+ }
496
+
497
+ export { CurrencyEngine }
@@ -0,0 +1,60 @@
1
+
2
+
3
+
4
+
5
+
6
+ const otherSettings = {
7
+ // Testnet (alphanet):
8
+ // tezosRpcNodes: [
9
+ // 'https://rpcalpha.tzbeta.net',
10
+ // 'https://alphanet-node.tzscan.io',
11
+ // 'https://alphanet.tezrpc.me'
12
+ // ],
13
+ // tezosApiServers: [
14
+ // 'https://api.alphanet.tzscan.io',
15
+ // 'http://node1.nyc.tezos.org.sg:8091'
16
+ // ]
17
+
18
+ // Mainnet:
19
+ tezosRpcNodes: [
20
+ 'https://rpc.tzbeta.net',
21
+ // 'https://teznode.letzbake.com',
22
+ 'https://mainnet.tezrpc.me'
23
+ ],
24
+ tezosApiServers: ['https://api.tzkt.io']
25
+ }
26
+
27
+ const defaultSettings = {
28
+ otherSettings,
29
+ fee: {
30
+ transaction: '1350',
31
+ reveal: '1300',
32
+ burn: '257000'
33
+ },
34
+ limit: {
35
+ gas: '10600',
36
+ storage: '277'
37
+ }
38
+ }
39
+ export const currencyInfo = {
40
+ // Basic currency information:
41
+ currencyCode: 'XTZ',
42
+ displayName: 'Tezos',
43
+ pluginId: 'tezos',
44
+ walletType: 'wallet:tezos',
45
+
46
+ defaultSettings,
47
+
48
+ addressExplorer: 'https://tzstats.com/%s',
49
+ transactionExplorer: 'https://tzstats.com/%s',
50
+
51
+ denominations: [
52
+ // An array of Objects of the possible denominations for this currency
53
+ {
54
+ name: 'XTZ',
55
+ multiplier: '1000000',
56
+ symbol: 't'
57
+ }
58
+ ],
59
+ metaTokens: []
60
+ }