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
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
|
+
[](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,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 }
|